Home > Enterprise >  Simplest way to extract file name with max minor version via PowerShell
Simplest way to extract file name with max minor version via PowerShell

Time:11-29

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
  • Related