Comparing Version Numbers

Hi There!

Apologies if this has been asked previously but I couldn't find the answer I was hoping for.

Basically, all I want to do is compare the OS X version against the version that I require in my script. So I'm retrieving the OS version using defaults read, but how can I compare this against another version number to see which is the greatest / newest?

Many thanks in advance...
davewg
:slight_smile:

You have to know ahead of time or lookup what the newest version is: off the net with maybe wget or from a file.. The OS does not know anything about what the newest version is.

I really do not understand what you are doing. If you are deploying something that requires version c of the OS (or some utility) on a box running version a, what do you intend to do in your code?

Code like that should abend with an error message complaining about versions, in the worst case.

A more user-friendly approach is to do what sysconf() does - learn about the system, then call code which is friendly to the environment. Find a way not to have to issue a nasty message. Especially if you want users to actually use the code.

Maybe it's in case software is running in a NFS mounted system on different systems.

Say you have AIX, you could capture the output of "oslevel" and run a test against it in the script. Actually probably better to use "uname -a" for portability.

It's just for a script in an installer package that needs to check the OS version to ensure it's suitable.

So I have for example decided that 10.4.6 is the required version my install needs and a variable with that value is already set in my script. Then, my script runs and detects that the OS X version of the target is 10.4.11. All I need to do now is to compare them, and then I can return the appropriate result to the installer...

Oh. details like that help a lot.
One way to do this try this for starters-

#!/bin/ksh
# input versionstring1   versionstring2  example: 10.10.1  10.8.3
# returns 0 if string1 = string2  
#          <0 if string1 < string2 
#           >0  if string1 > string2
# this assumes xx.xx.xx for version number
vercmp()
{
     IFS=.
     echo "$1"  | read a1 b1 c1
     echo "$2"  | read a2 b2 c2
     IFS=" "
     r1=$((a1 - a2))
     r2=$((b1 - b2))
     r3=$((c1 - c2))
     tot=$((r1 + r2 + r3))
     if [ $tot -eq 0 ] ; then
         print 0
         return 0
     fi
     if [[ $r1 -gt 0 || $r2 -gt 0 || $r3 -gt 0 ]] ; then  # changed
         print 1
         return 0
     fi
     retval="-1"        # changed
     echo  "$retval"  # changed

}

#usage:
if [ $(vercmp 10.10.1 10.2.4) -gt -1 ] ; then
       echo "version okay"
else
       echo "version too old"
fi

Apologies I should of been more clear in my post but thank you for your response.

I tried running the example code, but unforunately some errors were returned in Terminal (terminal shell set to /bin/ksh);

/Scripts/check[21]: [: ']' missing
/Scripts/check[21]: 8: not found [No such file or directory]
/Scripts/check[21]: -3: not found [No such file or directory]
/Scripts/check[25]: print: -1: unknown option
Usage: print [-enprs] [-f format] [-u fd] [string ...]
/Scripts/check[30]: [: argument expected
version too old

any ideas what the problem could be?

my bad - see the lines highlighted in red

That works a treat! thank you for your help :slight_smile:

I should just point out that whilst this comparison works ok in Leopard (10.5.6), on Tiger (10.4.11) it always returns success regardless of the numbers it is comparing. :frowning:

I'm not familiar with OS X, but usually version numbers are weighted. That may be the reason for the unrespected results on Tiger.
A script assuming max. 3 digits for any number could look like this:

#!/bin/ksh
# compare version numbers
# usage: vercmp <versionnr1> <versionnr2>
#         with format for versions xxx.xxx.xxx
# returns: 0 if versionnr1 equal or greater
#          1 if versionnr1 lower
vercmp()
{
        IFS=.
        echo "$1" |read a1 b1 c1
        echo "$2" |read a2 b2 c2
        IFS=" "
        ret=$(((a1 - a2) * 1000000 + (b1 - b2) * 1000 + c1 - c2))
        test $ret -gt -1
        return $?
}

vercmp 9.2.5 10.3.9
echo $?
vercmp 10.3.2 9.1.1
echo $?
vercmp 10.3.2 9.9.9
echo $?
vercmp 10.3.2 10.3.2
echo $?

returns

Tiger is definitely handling these numbers differently - when I run the code in Leopard the results are;

1
0
0
0

and in Tiger...

0
0
0
0

:confused: