Reputation: 590
I'm working on a script to automatically apply Windows Update files. I want to be able to apply them in a specific order, so I named them in the format #_FILENAME (ex: 1_windows10.0-kb4539571-x86_f63a97438b50173cd3362785fe102a6e5977956b.msu)
A standard loop through the directory won't apply them in order. I tested the following, but it doesn't sort the files correctly by name:
Get-ChildItem -Path "PATH HERE" -Recurse |
Where-Object {$_.Name -like "*msu*"} |
Sort-Object -Property Name | ForEach-Object{
Write-Host $_.Name
}
This would output something like this (which is not correct):
1_windows10.0-kb4539571-x86_f63a97438b50173cd3362785fe102a6e5977956b.msu
10_windows10.0-kb4570332-x86_88c4f7cce6237f42e24f07df1553e116b68400cb.msu
11_windows10.0-kb4577667-x86_1c6cc1cc8410f13a73bfe42e2d46c3a5434e53b3.msu
12_windows10.0-kb4577668-x86_38fd259988991bebc10d1ae38eb86cdc7d260f25.msu
13_windows10.0-kb4587735-x86_f67a582db752d5f01628ea5a71bd61b260f01eac.msu
14_windows10.0-kb4586793-x86_055782f642b3d5f52d5bb41f0fd21d2695a61881.msu
15_windows10.0-kb4594442-x86_c0131d2aa4753f40a9cedccef78a1fb9d3d5b7c1.msu
16_windows10.0-kb4592440-x86_3b7ee00f35ee72cf098e745199b9d34040855482.msu
17_windows10.0-kb4598230-x86_54c413174df931928c180e53a2d43f19dab00da2.msu
18_windows10.0-kb4598480-x86_cf41f4aad0b9fd35f922849d4e3d1f5587e09d2f.msu
19_windows10.0-kb4601345-x86_b4eb5e67d0b0325a79a8097623eab6b4eb7c5563.msu
2_windows10.0-kb4541331-x86_2add69875b760d19358a4dbd88a8b974ab7c36a6.msu
20_windows10.0-kb4601393-x86_3afe5b8330a10a49a01649a04459797194b3a057.msu
21_windows10.0-kb4577586-x86_947f151a8bb5a0b0797702e53431c52d56c02c32.msu
22_windows10.0-kb5000859-x86_f9156ae9cf5ae5daad986cb0f984d0872cb09055.msu
23_windows10.0-kb5000822-x86_6a9695aa4566b0edc63c25e0c0472f30b19efee0.msu
24_windows10.0-kb5001568-x86_ac43cdb614bfc2b4692ab2503efddc041a5b0c02.msu
25_windows10.0-kb5001638-x86_9bda1241132ff712a47d9d16cf0d978eec200a53.msu
26_windows10.0-kb5001404-x86_1ea8389ee96eff8140e22ed380c18843feb6090a.msu
27_windows10.0-kb5001342-x86_93e0b1c91098bb41afe81a7424a65b323be67cde.msu
28_windows10.0-kb5001407-x86_19a2574b1f0debc7d1587fc0c3f99d86f6864476.msu
29_windows10.0-kb5003243-x86_d291d08679c83237bc807fe45b0cc6e1370c61f1.msu
3_windows10.0-kb4554354-x86_2777d98ded121ce72a2e0c95ce274f60a7ad15e9.msu
30_windows10.0-kb5003171-x86_abffc1521d18a4fbf9d5aed15f75ea4094965f31.msu
31_windows10.0-kb5003711-x86_70a7ef9f67506eaeac5ae1747e90220e04e22492.msu
4_windows10.0-kb4549947-x86_76883e8e6c1f79903eb2a4d7c5781bc36c898242.msu
5_windows10.0-kb4550969-x86_f4ea0594e950dbeaa11af4252db2019e71131fb2.msu
6_windows10.0-kb4562562-x86_d1dc34578ef2e2dae2ff77f17bce5a4f51a20667.msu
7_windows10.0-kb4567513-x86_70baf70eb117086008b4b88cfc04ff73acfa6ad4.msu
8_windows10.0-kb4558997-x86_2adfc6fe55a1d1aad32eee373a629684b9aac292.msu
9_windows10.0-kb4566424-x86_2b9807df71713c5c4d09d85d80df682334f57e1f.msu
How can I get this to sort the files properly? Thanks!
Upvotes: 1
Views: 963
Reputation: 60060
This should do the trick:
Get-ChildItem -Path "PATH HERE" -Recurse |
Where-Object {$_.Name -like "*msu*"} |
Sort-Object {[int]$_.Name.Split('_')[0]} | ForEach-Object{
Write-Host $_.Name
}
_
and get the first element of the array:'1_windows10.0-kb4539571-x86_f63a97438b.....msu'.split('_')[0]
This would get the number 1
and [int]
to convert it to integer
from string
which then can be sorted.
I think it's important to mention why Abraham's approach using -as
might be better than casting the object type.
Using the same example as before. If we attempt to sort by the first integer
before the underscore, casting [int]
will work just fine, and it works well for OP too because he was certain of the naming convention of the files (all file names could be splitted by underscore
and the first item of the splitted array would always be a number). However if we are NOT sure if all items could be converted to int
we should use -as
to avoid terminating errors.
PS /> @'
3_windows10.0-kb4554354-x86_2777d98ded121ce72a2e0c95ce274f60a7ad15e9.msu
1_windows10.0-kb4539571-x86_f63a97438b50173cd3362785fe102a6e5977956b.msu
2_windows10.0-kb4541331-x86_2add69875b760d19358a4dbd88a8b974ab7c36a6.msu
asd_windows10.0-kb5003243-x86_d291d08679c83237bc807fe45b0cc6e1370c61f1.msu
4_windows10.0-kb4549947-x86_76883e8e6c1f79903eb2a4d7c5781bc36c898242.msu
'@ -split '\r?\n' | Sort-Object {[int]$_.Split('_')[0]}
Would yield:
Sort-Object : Cannot convert value "asd" to type "System.Int32". Error: "Input string was not in a correct format."
At line:7 char:21
+ '@ -split '\r?\n' | Sort-Object {[int]$_.Split('_')[0]}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidResult: (asd_windows10.0...6e1370c61f1.msu:PSObject) [Sort-Object], RuntimeException
+ FullyQualifiedErrorId : ExpressionEvaluation,Microsoft.PowerShell.Commands.SortObjectCommand
But with -as
we wouldn't have any terminating error:
PS /> @'
3_windows10.0-kb4554354-x86_2777d98ded121ce72a2e0c95ce274f60a7ad15e9.msu
1_windows10.0-kb4539571-x86_f63a97438b50173cd3362785fe102a6e5977956b.msu
2_windows10.0-kb4541331-x86_2add69875b760d19358a4dbd88a8b974ab7c36a6.msu
asd_windows10.0-kb5003243-x86_d291d08679c83237bc807fe45b0cc6e1370c61f1.msu
4_windows10.0-kb4549947-x86_76883e8e6c1f79903eb2a4d7c5781bc36c898242.msu
'@ -split '\r?\n' | Sort-Object {$_.Split('_')[0] -as [int]}
Yields:
asd_windows10.0-kb5003243-x86_d291d08679c83237bc807fe45b0cc6e1370c61f1.msu
1_windows10.0-kb4539571-x86_f63a97438b50173cd3362785fe102a6e5977956b.msu
2_windows10.0-kb4541331-x86_2add69875b760d19358a4dbd88a8b974ab7c36a6.msu
3_windows10.0-kb4554354-x86_2777d98ded121ce72a2e0c95ce274f60a7ad15e9.msu
4_windows10.0-kb4549947-x86_76883e8e6c1f79903eb2a4d7c5781bc36c898242.msu
Upvotes: 3