Reputation: 4187
We have a directory, which features many subdirectories (one per day) with serveral files in it. Unfortunately, files can be resent - so a file of 2020-01-01 can be resend (with slightly different filename, since a timestamp is added to the filename) on 2020-02-03. The structure looks something like this:
So the AFile of 2020-08-01 has been resent on 2020-08-02 at 3 PM.
I am now trying to retrieve a list with the most recent file per day, so I built up an array and populated it with all files below TopDir (recurively). So far so good, all files are found:
$path = "Y:\";
$FileArray = @()
$FileNameArray = @()
$FileArrayCounter = 0
foreach ($item in Get-ChildItem $path -Recurse)
{
if ($item.Extension -ne "")
{
$StringPart1, $StringPart2, $StringPart3, $StringPart4 = $item.Name.Split('_');
$FileNameShort = "{0}_{1}_{2}" -f $StringPart1.Trim(), $StringPart2.Trim(), $StringPart3.Trim();
$FileNameShort = $FileNameShort.Trim().ToUpper();
$FileArray += @{FileID = $FileArrayCounter; FileNameShort = $FileNameShort; FileName = $item.Name; FullName = $item.FullName; LastWriteTime = $item.LastWriteTime};
$FileArrayCounter ++;
}
}
$FileArray = $FileArray | sort FileNameShort; #@{Expression={"FileNameShort"}; Ascending=$True} #, @{Expression={"LastWriteTime"}; Descending=$True}
foreach($f in $FileArray)
{
Write-host($f.FileNameShort, $f.LastWriteTime)
}
Write-host($FileArrayCounter.ToString() + " Dateien gefunden");
The newly added column "FileNameShort" includes a substring of the filename. With this done, I receive two Rows for AFile_20200801
:
However, when I try to sort my array (see above code), the output is NOT sorted by name. Instead I receive something like the following:
What I want to achieve is a sorting by FileNameShort ASCENDING and LastWriteTime DESCENDING.
What am I missing here?
Upvotes: 0
Views: 59
Reputation: 25001
Your sort does not work because $FileArray
is an array of hash tables. The syntax Sort FileNameShort
is binding the FileNameShort
property to the -Property
parameter of Sort-Object
. However, the hash table does not contain a property called FileShortName
. You can see this if you run $FileArray[0] | Get-Member
.
If you create them as custom objects, the simple sort syntax works.
$FileArray += [pscustomobject]@{FileID = $FileArrayCounter; FileNameShort = $FileNameShort; FileName = $item.Name; FullName = $item.FullName; LastWriteTime = $item.LastWriteTime}
$FileArray | Sort FileNameShort # This will sort correctly
As an aside, I do not recommend using +=
to seemingly add elements to an array. It is best to either output the results inside of your loop and save the loop results or create a list with an .Add()
method. The problem with +=
is the current array is expanded into memory and those contents are then used to create a new array with the new items. As the array grows, it becomes increasingly non-performant. See below for a more efficient example.
$FileArray = foreach ($item in Get-ChildItem $path -Recurse)
{
if ($item.Extension -ne "")
{
$StringPart1, $StringPart2, $StringPart3, $StringPart4 = $item.Name.Split('_');
$FileNameShort = "{0}_{1}_{2}" -f $StringPart1.Trim(), $StringPart2.Trim(), $StringPart3.Trim();
$FileNameShort = $FileNameShort.Trim().ToUpper();
# Outputting custom object here
[pscustomobject]@{FileID = $FileArrayCounter; FileNameShort = $FileNameShort; FileName = $item.Name; FullName = $item.FullName; LastWriteTime = $item.LastWriteTime};
$FileArrayCounter ++;
}
}
Upvotes: 1
Reputation: 4187
I just found the solution:
$FileArray = $FileArray | sort @{Expression={[string]$_.FileNameShort}; Ascending=$True}, @{Expression={[datetime]$_.LastWriteTime}; Descending=$True}
Still I don't know, why the first sorting did not work as expected.
Upvotes: 0