Assume with following list of snapshots files in a folder
app-SNAPSHOT-01.jar
app-SNAPSHOT-02.jar
app-SNAPSHOT-03.jar
app-SNAPSHOT-04.jar
...
app-SNAPSHOT-xy.jar
What is the simplest way to extract the latest (max minor version) file name (i.e. app-SNAPSHOT-xy.jar) via PowerShell
script?
So far I have tried I tried
$maxVersion = ls -Filter app-SNAPSHOT-* | sort { [version]($_.Name.split("-")[-1]) } -Descending | select -Index 0
but it throws an error Error: "Version string portion was too short or too long."
UPDATE
Thanks to @Santiago Squarzon for the answer
The actual file name is a bit complicated than above example, which come with timestamp
#20211128.031305 being timestamp
app-SNAPSHOT-0.0.2-20211128.031305-10.jar
CodePudding user response:
To give you a short explanation of why you are getting that exception. See Version Class
for more details.
All defined components must be integers greater than or equal to 0. The format of the version number is as follows (optional components are shown in square brackets ([ and ]):
major.minor[.build[.revision]]
Example:
PS /> [version]'1.0.1'
Major Minor Build Revision
----- ----- ----- --------
1 0 1 -1
In this case, you can't cast [version]
to the numbers because they don't follow the version format. If you want to convert the numbers between the hyphen and the .jar
extension it would require manipulation and there is no logic we can follow unless you specify so.
If you simply need to sort by the numbers and get the greater one this is how you can do it:
Get-ChildItem . -Filter *.jar |
Sort-Object {
[int][regex]::Match($_.Name, '(?<=-)\d (?=\.jar)').Value
} -Descending | Select-Object -First 1
As an example, I created some files which default order look like this:
Name
----
app-SNAPSHOT-01.jar
app-SNAPSHOT-01000.jar
app-SNAPSHOT-04.jar
app-SNAPSHOT-19x9.jar
app-SNAPSHOT-630.jar
And after sorting (Note that app-SNAPSHOT-19x9.jar
is the last one because it does not match the regex
pattern):
Name
----
app-SNAPSHOT-01000.jar
app-SNAPSHOT-630.jar
app-SNAPSHOT-04.jar
app-SNAPSHOT-01.jar
app-SNAPSHOT-19x9.jar
EDIT
This is how you would sort the files that have the naming convention shown on your edit, first by DateTime
and then by version (the numbers between -
and the .jar
extension)
@'
app-SNAPSHOT-0.0.2-20211128.031305-13.jar
app-SNAPSHOT-0.0.2-20211129.011305-12.jar
app-SNAPSHOT-0.0.2-20211122.051305-10.jar
app-SNAPSHOT-0.0.2-20211128.081305-10.jar
app-SNAPSHOT-0.0.2-20211129.021305-08.jar
'@ -split '\r?\n' | Sort-Object {
[datetime]::ParseExact(
[regex]::Match($_, '(?<=-)\d{8}\.\d{6}(?=-)').Value,
'yyyyMMdd.HHmmss',
$null
)
},
{
[int][regex]::Match($_, '(?<=-)\d (?=\.jar)').Value
} -Descending
After sorting the result would be:
app-SNAPSHOT-0.0.2-20211129.021305-08.jar
app-SNAPSHOT-0.0.2-20211129.011305-12.jar
app-SNAPSHOT-0.0.2-20211128.081305-10.jar
app-SNAPSHOT-0.0.2-20211128.031305-13.jar
app-SNAPSHOT-0.0.2-20211122.051305-10.jar
In the example above, the "newest" file would be app-SNAPSHOT-0.0.2-20211129.021305-08.jar
. Even though app-SNAPSHOT-0.0.2-20211129.011305-12.jar
has a higher version number it has a less recent timestamp than the other one (by 1 hour exactly):
[datetime]::ParseExact('20211129.021305', 'yyyyMMdd.HHmmss', $null) -gt
[datetime]::ParseExact('20211129.011305', 'yyyyMMdd.HHmmss', $null) # => True