Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare version numbers in batch file

Tags:

batch-file

I am using the below to get the file version of a file:

sigcheck.exe -n "C:\some.exe"

The above returns something like: 12,2,0,6837.

How can I take this version number. Remove the ,'s to make 1 large number & then compare it against another version number which is stored in the name of a txt file such as: 12.3.0.7218.txt (ie do a similar thing to the file version stored in the file name: remove the .'s to make a large number).

I need to be able to perform some code in the batch file if the file that contains the version in its name is later than the applications file version ie install an update.

like image 407
Adam Chetnik Avatar asked Dec 11 '22 16:12

Adam Chetnik


1 Answers

You cannot simply remove the commas (node delimiters) and compare a single number - it may not give the correct result.

For example, 12.3 and 1.23 would both result in 123, leading to a false conclusion of equivalence. You must compare nodes one at a time, starting from the left. As soon as you find a difference in a node, then you have your answer. If the nodes are equivalent until one version runs out of nodes, then the version with more nodes is larger: 1.2.2 > 1.2

Edit
Sometimes companies tack on a letter suffix to a node. The letter should be considered a new node. Search and replace can be used to introduce a node delimiter before each letter. Search and replace is case insensitive, so a equals A.

@echo off
setlocal
call :testVersions  2.1      1.9
call :testVersions "2,1"     1-9
call :testVersions  1.9      2.1
call :testVersions  1.13     1.4
call :testVersions  1.4      1.13
call :testVersions  1.3.4    1.3.4
call :testVersions  1.3.4    1.3.5
call :testVersions  1.3.5    1.3.4
call :testVersions  1.3.5    1.3.5.1
call :testVersions  1.3.5.1  1.3.5
call :testVersions  1.3b     1.3
call :testVersions  1.3      1.3b
call :testVersions  1.10a    1.9
call :testVersions  1.9      1.10a
call :testVersions  1.9a     1.9b
call :testVersions  1.9b     1.9a
call :testVersions  1.9a     1.9A
exit /b


:testVersions  version1  version2
call :compareVersions %1 %2
if %errorlevel% == 1 set "result=greater than"
if %errorlevel% == -1 set "result=less than"
if %errorlevel% == 0 set "result=equal to"
echo %~1 is %result% %~2
exit /b


:compareVersions  version1  version2
::
:: Compares two version numbers and returns the result in the ERRORLEVEL
::
:: Returns 1 if version1 > version2
::         0 if version1 = version2
::        -1 if version1 < version2
::
:: The nodes must be delimited by . or , or -
::
:: Nodes are normally strictly numeric, without a 0 prefix. A letter suffix
:: is treated as a separate node
::
setlocal enableDelayedExpansion
set "v1=%~1"
set "v2=%~2"
call :divideLetters v1
call :divideLetters v2
:loop
call :parseNode "%v1%" n1 v1
call :parseNode "%v2%" n2 v2
if %n1% gtr %n2% exit /b 1
if %n1% lss %n2% exit /b -1
if not defined v1 if not defined v2 exit /b 0
if not defined v1 exit /b -1
if not defined v2 exit /b 1
goto :loop


:parseNode  version  nodeVar  remainderVar
for /f "tokens=1* delims=.,-" %%A in ("%~1") do (
  set "%~2=%%A"
  set "%~3=%%B"
)
exit /b


:divideLetters  versionVar
for %%C in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do set "%~1=!%~1:%%C=.%%C!"
exit /b

--OUTPUT--

2.1 is greater than 1.9
2,1 is greater than 1-9
1.9 is less than 2.1
1.13 is greater than 1.4
1.4 is less than 1.13
1.3.4 is equal to 1.3.4
1.3.4 is less than 1.3.5
1.3.5 is greater than 1.3.4
1.3.5 is less than 1.3.5.1
1.3.5.1 is greater than 1.3.5
1.3b is greater than 1.3
1.3 is less than 1.3b
1.10a is greater than 1.9
1.9 is less than 1.10a
1.9a is less than 1.9b
1.9b is greater than 1.9a
1.9a is equal to 1.9A
like image 173
dbenham Avatar answered Feb 28 '23 13:02

dbenham