Skip to content
shellhacks.dev
Shell Scripting

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.

1 min read
Summarize in AI

A script needs to know whether one version is older than another, and it must run on systems where sort has no -V option.

Shell
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' | sort
Text
1.9 vs 1.10:   lt
2.0 vs 2.0.0:  eq
1.2.3 vs 1.2:  gt
1.10
1.9

The 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.

Share

More snippets

Shell Scripting

Return Text from a Function in POSIX sh

A POSIX sh function returns text by printing it, and the caller captures the output with command substitution. Variables set inside are lost, and trailing newlines go.

1 min read

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.