Page 1 of 1
How to compare versions in a Bash script? (Solved)
Posted: Mon 25 Aug 2014, 18:44
by linus.cl
Hello!
How can I compare two versions in my Bash script?
I have two versions:
They are saved in two variables: $newversion and $oldversion
I try to compare them.
I hope, you can help me...
Posted: Mon 25 Aug 2014, 19:53
by 6502coder
You mean that you just want to test two shell variables to see if they are the same string? That's easy:
Code: Select all
if [ $newversion = $oldversion ]
then
echo same
else
echo different
fi
Posted: Mon 25 Aug 2014, 19:57
by linus.cl
No, i'd like to check if $newversion is newer.
I found an application: vercmp.
https://www.archlinux.org/pacman/vercmp.8.html
But I can't use it. (I don't understand it)
Posted: Mon 25 Aug 2014, 22:29
by RSH
Code: Select all
if vercmp ${NEWVERSION} gt ${OLDVERSION} ; then
echo $NEWVERSION
fi
Posted: Tue 26 Aug 2014, 02:27
by MochiMoppel
linus.cl wrote:I found an application: vercmp.
No need for an application. Try this:
Code: Select all
newversion="2.7.1-i486s"
oldversion="2.3-2-spup"
[[ "$newversion" > "$oldversion" ]] && echo "newversion is newer" || echo "oldversion is newer"
The
> operator compares 2 strings by their alphabetic ASCII order. Requires a double bracket test construct to work.
Posted: Tue 26 Aug 2014, 14:20
by gcmartin
Hello @Linus.cl
Noticing some of the very good things you are aiming into the community, you may
find this tool to have "tremendous " advantage to your use and development efforts. Install and observe. It will meet much much more than you ask while accelerating your work efforts. And, there is no system penalty in its presence as a tool.
Here to help
Posted: Tue 26 Aug 2014, 14:39
by jamesbond
There are a few versions of "vercmp" floating around. Since you're building for Puppy, might as well use Puppy's own vercmp. It's here:
https://github.com/puppylinux-woof-CE/w ... t/vercmp.c. If you google "barry kauler vercmp" you will find a few links.
Posted: Thu 28 Aug 2014, 02:16
by technosaurus
sort -V or sort --version-sort works too
use head -n1 or tail -n1 for the oldest/newest (works for comparing 2 or more)
Posted: Mon 15 Dec 2014, 18:11
by Karl Godt
I would use case for that
Code: Select all
case $BASH_VERSION in
1.*) : do_something;;
2.[0-2].*) : do_something_else;;
2.3.*) echo OLD VERSION;;
2.[4-6].*) : do_something_else_more;;
2.7.*) echo NEW VERSION;;
*) echo UNHANDLED bash version $BASH_VERSION;;
esac
5.2 Bash Variables
These variables are set or used by Bash, but other shells do not normally treat them specially.
BASH_VERSINFO
A readonly array variable (see Arrays) whose members hold version information for this instance of Bash. The values assigned to the array members are as follows:
BASH_VERSINFO[0]
The major version number (the release).
BASH_VERSINFO[1]
The minor version number (the version).
BASH_VERSINFO[2]
The patch level.
BASH_VERSINFO[3]
The build version.
BASH_VERSINFO[4]
The release status (e.g., beta1).
BASH_VERSINFO[5]
The value of MACHTYPE.
BASH_VERSION
The version number of the current instance of Bash.
http://www.gnu.org/software/bash/manual ... oking-Bash
Bash version 2.Y may not know some of these variables .
Posted: Thu 30 Apr 2020, 14:13
by goingnuts
From above inputs I put together below shell-version of vercmp which also works with ash/busybox only systems:
Code: Select all
#!/bin/sh
help () {
echo "usage: vercmp-shell version1 lt|gt|le|ge|eq version2
return value 0 if true, else 1"
}
[ $# -ne 3 ] && help && exit 2
case "$2" in
lt) [ "$1" != "$3" ] && [ "$(echo $1,$3 | tr ',' '\n' | sort -k1,1n | head -n1)" = "$1" ] && exit 0 || exit 1;;
gt) [ "$1" != "$3" ] && [ "$(echo $1,$3 | tr ',' '\n' | sort -k1,1n | tail -n1)" = "$1" ] && exit 0 || exit 1;;
le) [ "$1" = "$3" ] || [ "$(echo $1,$3 | tr ',' '\n' | sort -k1,1n | head -n1)" = "$1" ] && exit 0 || exit 1;;
ge) [ "$1" = "$3" ] || [ "$(echo $1,$3 | tr ',' '\n' | sort -k1,1n | tail -n1)" = "$1" ] && exit 0 || exit 1;;
eq) [ "$1" = "$3" ] && exit 0 || exit 1;;
*) help && exit 1;;
esac
exit
Posted: Fri 01 May 2020, 02:42
by MochiMoppel
Nice. However unlike the binary vercmp it might give false results when the version string contains commas, e.g. "GNU bash, version 4.4.12(1)-release (i686-pc-linux-gnu)"
I think it would be better to change
Code: Select all
echo $1,$3 | tr ',' '\n' | sort -k1,1n
to something more robust like
Code: Select all
printf '%s\n%s' "$1" "$3" | sort -k1,1n
Would still work with ash
Posted: Fri 01 May 2020, 18:00
by goingnuts
Agree - thanks for improvement input!
Follow up 20200503: For robustness one could also change from:
Code: Select all
echo $1,$3 | tr ',' '\n' | sort -k1,1n
to:
Code: Select all
echo $1/$3 | tr '/' '\n' | sort -k1,1n
or to eliminate the use of
tr one could change to:
The
printf is sure best way but not all systems has it - echo seems more likely to be everywhere...but might not always support -e though.