Seraph Cui
Seraph Cui

Reputation: 11

How to get latest version number using batch

I have a folder that contains multiple sub-directories

Directories example

The version format is [major].[minor].[update][phase][build], like 1.0.0d0. And valid phases are d(ev), a(lpha), b(eta), f(inal), please note d < a < b < f.

I'd like to get the latest version number which is 16.0.0a2 using batch script. I write such codes, but doesn't work, because the sub-directories are sorted by alphabetical order. So it will give a result 16.0.0d24.

SET BASEPATH=.....
SET TEMPFILE=%TEMP%\%~n0%RANDOM%
echo get latest export.
DIR /A:D /B /ON "%BASEPATH%" > "%TEMPFILE%"
FOR /F "usebackq delims=;" %%I IN ("%TEMPFILE%") DO (SET LATEST_VERSION=%%I)
echo LATEST_VERSION

Upvotes: 1

Views: 980

Answers (3)

aschipfl
aschipfl

Reputation: 34909

The following script does what you want:

@echo off
setlocal EnableExtensions EnableDelayedExpansion

set "LOC=%~1"
if not defined LOC set "LOC=."
set /A "PADV=100, PADB=10000"
set "SRCH=d" & set "REPL=@"

for /F "tokens=1,2,* delims=." %%A in ('
    dir /B /A:D /O:D /T:C "%LOC%" ^| ^
        findstr /I /R "[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*[dabf][0-9][0-9]*"
') do (
    set /A "MAJOR=%%A+PADV, MINOR=%%B+PADV"
    for /F "tokens=1,* delims=DdAaBbFf" %%E in ("%%C") do (
        set /A "FIX=%%E+PADV, BUILD=%%F+PADB"
        set "PHASE=%%C" & set "PHASE=!PHASE:*%%E=!" & set "PHASE=!PHASE:~,1!"
        set "PHASE=!PHASE:%SRCH%=%REPL%!"
    )
    set "VERSION[!MAJOR!.!MINOR!.!FIX!!PHASE!!BUILD!]=%%A.%%B.%%C"
)

for /F "tokens=2 delims==" %%V in ('2^> nul set VERSION[') do (
    set "LATEST=%%V"
    echo(%%V
)
if defined LATEST echo Latest: & echo(%LATEST%

endlocal
exit /B

The basic concept is to adapt the version numbers so that (alpha-)numeric sorting provides the same result as alphabetic sorting. This can be achieved by adding a great number to every numeric part of the version numbers so that each one always has got the same number of digits. In addition, since the priority of the phase figure is not of alphabetical order, adequate replacements are done.

The core idea is taken from this answer and is credited to Aacini.

Upvotes: 2

MC ND
MC ND

Reputation: 70923

Similar code to the one posted by aschipfl. Same value padding approach for each segment, just a different handling of name splitting and value padding.

@echo off
    setlocal enableextensions disabledelayedexpansion

    rem Give a path as argument or use current active directory
    for %%a in ("%~f1.") do set "target=%%~fa"

    rem Prepare variables to handle phase order correction and 
    rem storage of intermediate/final values
    set /a "_d=0", "_a=1", "_b=2", "_f=3"
    set "lastValue="
    set "lastVersion="

    rem %%a : Search the folders and split their name using dot as delimiter
    rem       %%a = major
    rem       %%b = minor
    rem       %%c = update + phase + build
    rem %%d : split %%c using [dabf] as delimters to obtain 
    rem       %%d = update
    rem       %%e = build
    rem %%f : split %%c using numbers as delimiters to obtain
    rem       %%f = phase 
    set "num=[0-9][0-9]*"
    for /f "tokens=1-3 delims=." %%a in ('
        dir /b /ad /o-d "%target%"
        ^| findstr /r /i /x /c:"%num%\.%num%\.%num%[dabf]%num%"
    ') do for /f "tokens=1,2 delims=dDaAbBfF" %%d in ( "%%c"
    )  do for /f "delims=0123456789" %%f in ( "%%c"
    )  do (
        rem Folder name has been splitted. Now, convert each of the segments
        rem to a numerical value, adding 1E6 to get a proper padding as all 
        rem values will be handled as strings to avoid limits in batch 
        rem arithmetic for values over 2^31
        rem Note that %%f is not being iterated here as the values to use 
        rem for phase padding have been previously defined
        for %%v in (
            %%a %%b %%d %%e
        ) do if not defined _%%v set /a "_%%v=1000000 + %%v"

        rem Obtain the properly padded version of the folder segments
        setlocal enabledelayedexpansion
        for /f "tokens=1,2" %%i in (
            "!_%%a!!_%%b!!_%%d!!_%%f!!_%%e! !lastValue!"
        ) do (
            endlocal
            rem Determine if we have found a newer version
            if "%%i" gtr "%%j" (
                set "lastValue=%%i"
                set "lastVersion=%%a.%%b.%%c"
            )
        )
    )

    if defined lastVersion (
        echo Latest version found is : %lastVersion%
    ) else (
        echo No matching folders
    )

Upvotes: 1

Stephan
Stephan

Reputation: 56180

the creation date should be a good criterium for sorting in this case:

...
echo get latest export.
FOR /F "delims=" %%I IN ('DIR /AD /B /OD /TC "%BASEPATH%"') DO SET "LATEST_VERSION=%%I"
echo %LATEST_VERSION%

dir-parameters:
/OD sort by date/time
/TC pick the creation date (instead of default "last modification date")
/AD show directories only
/B show just the names, no header, no sizes, dates etc, no summary.

If there max be other folders too, get your version-folders with dir ... "%basedir%\??.?.*" ("two chars, dot, one char, dot, whatever")

Upvotes: 1

Related Questions