I'm trying to collect some file properties using PowerShell within Win 2008. To do so, I've created the following script.
# BASIC PARAMETER IF NOT SET
param(
$REGEX='.*'
)
# CURRENT DATE FROM 00H
$DATAATUAL = Get-Date -Hour 0 -Minute 0 -Second 0 -Day 1 # DAY 1 FOR TESTING ONLY
# APPLICATION'S FILE PATH
$PATH = "C:\FTP\import\"
# FILE LIST WITH SELECTED FILES FROM REGULAR EXPRESSION
$FILELIST = Get-ChildItem -Path $PATH | Where-Object { ($_.LastWriteTime -ge $DATAATUAL) -and ($_.Name -cmatch "$REGEX") } | Select-Object -ExpandProperty Name
# OUTPUT IN A SORT OF CSV FORMAT
if ($FILELIST -ne $null) {
Write-Host "name;suffix;fileprocstart;filesize;filewrite"
ForEach ($FILE in $FILELIST) {
# FILE NAME PREFFIX AND SUFFIX
$FILENAME = Select-String -InputObject $FILE -CaseSensitive -Pattern "(^\d )_($REGEX)"
# FILE TIMESTAMP CONVERTION TO EPOCH UTC-0
$FILEPROCSTART = $FILENAME.Matches.Groups[1].value
$FILEPROCSTART = [datetime]::ParseExact($FILEPROCSTART,"yyyyMMddHHmmss",$null) | Get-Date -UFormat "%s"
$FILEPROCSTART = $($FILEPROCSTART -as [long]) 10800 # TIMEZONE CORRECTION - ADDED 3H TO BECOME UTC-0
$FILESUFFIX = $FILENAME.Matches.Groups[2].value
# FILE SIZE AND WRITE TIME
$FILESIZE = Get-ChildItem -Path $PATH -Filter $FILE | Select-Object -ExpandProperty Length
$FILEWRITE = Get-ChildItem -Path $PATH -Filter $FILE | Select-Object -ExpandProperty LastWriteTime | Get-Date -UFormat "%s"
# OUTPUT
Write-Host "$FILENAME;$FILESUFFIX;$FILEPROCSTART;$FILESIZE;$FILEWRITE"
}
}
# NO FILES FOUND
Else {
Write-Host "Empty"
}
I can start it like so:
script.ps1 -REGEX 'pattern'
It results in a list like this:
name;suffix;fileprocstart;filesize;filewrite
20220709101112_cacs1_v83.txt;cacs1_v83.txt;1657361472;5;1657397022,47321
20220709101112_cacs1_v83.txt.log;cacs1_v83.txt.log;1657361472;5;1657397041,83271
20220709101112_cacs2_v83.txt;cacs2_v83.txt;1657361472;5;1657397039,70775
20220709101112_cacs3_v83.txt.log;cacs3_v83.txt.log;1657361472;5;1657397038,03647
20220709101112_cakauto4.txt;cakauto4.txt;1657361472;5;1657397037,48906
20220709111112_coord_multicanal.txt.log;coord_multicanal.txt.log;1657365072;5;1657398468,95865
All files are generated on a daily basis and have a format similar to this:
20220709101112_cacs1_v83.txt
20220709101112_cacs1_v83.txt.log
20220709101112_cacs2_v83.txt
20220709101112_cacs3_v83.txt.log
20220709101112_cakauto4.txt
20220709101112_coord_multicanal.txt.log
Basically, the script outputs the file name, file suffix (no timestamp), file timestamp (unix format), file size and Last Write time (unix format), all in a sort of CSV format. It is meant to be started by another system to collect those properties.
It kind of works, but I can't help thinking there must be a better way to do that.
Any considerations on how to improve it?
CodePudding user response:
I'm not sure if I got it right but if I understand this right:
Basically, the script outputs the file name, file suffix, file name timestamp, file size and Last Write time, all in a sort of CSV format. It is meant to be started by another system to collect those properties.
This should be all you need to start with:
$ComputerName = 'RemoteW2K8Computer'
Invoke-Command -ComputerName $ComputerName -ScriptBlock {
Get-ChildItem -Path 'C:\FTP\import' |
Select-Object -Property BaseName,Extension,Length,LastWriteTime,
@{Name = 'FileNameTimeStamp'; Expression = {($_.BaseName -split '_')[0]}}
}
CodePudding user response:
Using @Olaf great tips, I've rewritten the script this way.
param($REGEX='.*')
$DATAATUAL = Get-Date -Hour 0 -Minute 0 -Second 0 -Day 1 # DAY 1 FOR TESTING ONLY
$PATH = "C:\FTP\import"
$TZ = [TimeZoneInfo]::FindSystemTimeZoneById("E. South America Standard Time")
$FILELIST = Get-ChildItem -Path $PATH |
Where-Object { ($_.LastWriteTime -ge $DATAATUAL) -and ($_.Name -cmatch "$REGEX") } |
Select-Object -Property Name,Length,
@{Name = 'Suffix'; Expression = { ($_.Name -split '_',2)[1] } },
@{Name = 'ProcStart'; Expression = {
$PROCSTART = ($_.Name -split '_')[0];
$PROCSTART = [datetime]::ParseExact($PROCSTART,"yyyyMMddHHmmss",$null);
[TimeZoneInfo]::ConvertTimeToUtc($PROCSTART, $TZ) | Get-Date -UFormat "%s";
} },
@{Name = 'FileWrite' ; Expression = {
$WRITETIME = $_.LastWriteTime;
[TimeZoneInfo]::ConvertTimeToUtc($WRITETIME) | Get-Date -UFormat "%s";
} }
if ($FILELIST -ne $null) {
Write-Host "name;suffix;procstart;filesize;filewrite"
# $FILELIST | ConvertTo-Csv -Delimiter ';' -NoTypeInformation
ForEach ($FILE in $FILELIST) {
$FILENAME = $FILE.Name
$FILESUFFIX = $FILE.Suffix
$FILESIZE = $FILE.Length
$FILEPROCSTART = $FILE.ProcStart
$FILEWRITE = $FILE.FileWrite
Write-Host "$FILENAME;$FILESUFFIX;$FILESIZE;$FILEPROCSTART;$FILEWRITE"
}
}
Else {
Write-Host "Empty"
}
As said, the output is in a CSV format.
name;suffix;procstart;filesize;filewrite
20220709101112_cacs1_v83.txt;cacs1_v83.txt;5;1657361472;1657397022,47321
20220709101112_cacs1_v83.txt.log;cacs1_v83.txt.log;5;1657361472;1657397041,83271
If I use ConvertTo-Csv
(much simpler) instead of ForEach
, the output would also be a CSV.
However, it places quotation marks that mess up other conversions to JSON elsewhere (maybe I can improve that later).
# $FILELIST | ConvertTo-Csv -Delimiter ';' -NoTypeInformation
"Name";"Length";"Suffix";"ProcStart";"FileWrite"
"20220709101112_cacs1_v83.txt";"5";"cacs1_v83.txt";"1657361472";"1657397022,47321"
"20220709101112_cacs1_v83.txt.log";"5";"cacs1_v83.txt.log";"1657361472";"1657397041,83271"
The other system convert it to this (I can't use ConvertTo-Json in Win2008 :-/):
{
"\"Name\"": "\"20220709101112_cacs1_v83.txt\"",
"\"Length\"": "\"5\"",
"\"Suffix\"": "\"cacs1_v83.txt\"",
"\"ProcStart\"": "\"1657361472\"",
"\"FileWrite\"": "\"1657397022,47321\""
}
Therefore, I find that writing the values with ForEach
gives me a cleaner output.
Also, for fun, measuring with Measure-Command, I found that the new script is a bit faster. The previous script takes about 24 milliseconds to complete while using a small dataset. Now, the new one takes about 13 milliseconds with the same dataset.
All in all, a small, but good improvement, I guess.
Cheers to @Olaf for pointing to a better script and for his patience. Thank you.