Take the 2-minute tour ×
Ask Different is a question and answer site for power users of Apple hardware and software. It's 100% free, no registration required.

Trying to write a script that searches for the version of the Application then returns the value. My problem is the value is three to four intergers long (example 4.3.2).

I have searched for a while and can't find any syntax that would allow you to use a != or -ge for anything higher than a number with periods in it. Just wondering if anyone has a better way or I will just keep adding for every version release.

What I want

else if [ $version1 -ge "9.0.8" ]; then

How it is written now

vercheck=`mdls -name kMDItemVersion /Applications/iMovie.app`
version=`echo ${vercheck:17}`
version1=`echo ${version:1:5}`

[...]

else if [ $version1 = "9.0.8" ]; [ $version1 = "9.1.1" ]; then
    echo "You already have this version or a higher version installed"
    exit 0
share|improve this question
1  
See stackoverflow.com/questions/4023830/… –  Matteo Mar 1 '13 at 16:59
    
Perfect thanks for the link –  balooga1 Mar 1 '13 at 17:39
    
The solution Matteo linked to seems way more complicated than it needs to be, unless I'm misunderstanding something. I've posted a shorter solution below. –  TJ Luoma Mar 6 at 20:39
    
BTW mdls -raw -name kMDItemVersion /Applications/iMovie.app will give you just the version number without the superfluous stuff. –  TJ Luoma Mar 6 at 20:40
add comment

3 Answers 3

Actually, comparing version numbers is pretty straightforward (at least as long as they are strictly numeric) as they are hierarchically structured left to right. A sequential comparison in that same order will yield a clear result.

The following bash function will return 0 (true) if two version numbers are not equal, 1 (false) if they are, as long as the variables $version_1 and $version_2 both contain only an arbitrary number of digit groups separated by periods:

function versions_not_equal {
    while [[ $version_1 != "0" || $version_2 != "0" ]]; do
        (( ${version_1%%.*} != ${version_2%%.*} )) && return 0
        [[ ${version_1} =~ "." ]] && version_1="${version_1#*.}" || version_1=0
        [[ ${version_2} =~ "." ]] && version_2="${version_2#*.}" || version_2=0
    done
    false
}

Implementing other comparisons, like greater or equal, is as simple as changing the comparison operator of the arithmetic evaluation (i.e. (( ${version_1%%.*} >= "${version_2%%.*}" ))).

share|improve this answer
add comment

I can give you a long example of "if the checked version is between min and max" and you can optimize it for your needs changing head -1/tail -1 and cutting 1 variable:

min_ver="a-1.1.1"
max_ver="a-9.1.1"
check_ver="a-2.2.9"
if [ "$( echo -e "${min_ver}\\n${max_ver}\\n${check_ver}" | sort --sort=version | head -2 | tail -1)" == ${check_ver} ]
then
  echo YES - apply  ${check_ver}
fi
share|improve this answer
add comment

I believe I adapted this slightly from http://bashscripts.org/forum/viewtopic.php?f=16&t=1248. I like it because it's fairly compact and readable.

This is optional, but desirable IMO:

if [ "$#" != "2" ]
then
    echo "$0 requires exactly two arguments."
    exit 2
fi

Here's the meat:

I always use $1 for "the locally installed version" and $2 for "the version I am comparing against" so if this leaves me with $? = 1 I need to update, otherwise I'm up-to-date (or even ahead):

function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }

if [ $(version $1) -gt $(version $2) ]; then
    echo "$1 is newer than $2"
    exit 0
elif [ $(version $1) -lt $(version $2) ]; then
    echo "$1 is older than $2"
    exit 1
else
    echo "$1 is identical to $2"
    exit 0
fi

If all you cared about was whether $1 was up to date (that is, equal to or greater than $2) you could make it even simpler:

if [ $(version $1) -ge $(version $2) ]; then
    echo "No Newer Version Available"
    exit 0
fi

Any code below that will only be executed if there is a newer version available. Otherwise the script will exit cleanly at that point.

p.s.: I do this in /bin/zsh not /bin/bash but I don't think it makes a difference in this case.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.