Reputation: 11
I have a folder that contains multiple sub-directories
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
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
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
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