Compare Dotted Version Numbers in POSIX sh
Compare dotted version numbers in POSIX sh by splitting on dots and comparing each field as an integer. Plain sort puts 1.10 before 1.9, and sort -V is a GNU option.
A script needs to know whether one version is older than another, and it must run on systems where sort has no -V option.
vercmp() {
a=$1 b=$2
while [ -n "$a$b" ]; do
x=${a%%.*} y=${b%%.*}
[ "${x:-0}" -lt "${y:-0}" ] && { echo lt; return; }
[ "${x:-0}" -gt "${y:-0}" ] && { echo gt; return; }
case $a in *.*) a=${a#*.} ;; *) a= ;; esac
case $b in *.*) b=${b#*.} ;; *) b= ;; esac
done
echo eq
}
echo "1.9 vs 1.10: $(vercmp 1.9 1.10)"
echo "2.0 vs 2.0.0: $(vercmp 2.0 2.0.0)"
echo "1.2.3 vs 1.2: $(vercmp 1.2.3 1.2)"
printf '1.9\n1.10\n' | sort1.9 vs 1.10: lt
2.0 vs 2.0.0: eq
1.2.3 vs 1.2: gt
1.10
1.9The function peels one dot-separated field at a time with ${a%%.*} and ${a#*.}, compares the fields as integers and treats a missing field as 0, so 2.0 equals 2.0.0 and 1.2.3 is greater than 1.2. Plain sort compares text, which is why the last two lines show 1.10 before 1.9. The expansions are in the specification of parameter expansion, and -V appears only in the GNU sort manual.
This handles numeric dotted versions only. A suffix such as 1.2.3-rc1 or 1.0b2 breaks the integer test, so strip or reject it first. On GNU systems sort -V is shorter, and Debian has dpkg --compare-versions.