How to compare two version numbers in a shell script

Question: I am writing a shell script in which I need to compare two version number strings (e.g., "1.2.30" and "1.3.0") to determine which version is higher or lower than the other. Is there a way to compare two version number strings in a shell script?

When you are writing a shell script, there are cases where you need to compare two version numbers, and proceed differently depending on whether one version number is higher/lower than the other. For example, you want to check for the minimum version requirement (i.e., $version ≥ 1.3.0). Or you want to write a conditional statement where the condition is defined by a specific range of version numbers (e.g., 1.0.0 ≤ $version ≤ 2.3.1).

If you want to compare two strings in version format (i.e., "X.Y.Z") in a shell script, one easy way is to use sort command. With "-V" option, the sort command can sort version numbers within text (in an increasing order by default). With "-rV" option, it can sort version numbers in a decreasing order.

Now let's see how we can use the sort command to compare version numbers in a shell script.

For version number string comparison, the following function definitions come in handy. Note that these functions use the sort command.

function version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }
function version_le() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" == "$1"; }
function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"; }
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }

These functions perform, respectively, "greater-than", "less than or equal to", "less than", and "greater than or equal to" operations against two specified version numbers. You will need to use bash shell due to function definitions.

Below is an example bash script that compares two version numbers.

#!/bin/bash

VERSION=$1
VERSION2=$2

function version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }
function version_le() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" == "$1"; }
function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"; }
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }

if version_gt $VERSION $VERSION2; then
   echo "$VERSION is greater than $VERSION2"
fi

if version_le $VERSION $VERSION2; then
   echo "$VERSION is less than or equal to $VERSION2"
fi

if version_lt $VERSION $VERSION2; then
   echo "$VERSION is less than $VERSION2"
fi

if version_ge $VERSION $VERSION2; then
   echo "$VERSION is greater than or equal to $VERSION2"
fi
Download this article as ad-free PDF (made possible by your kind donation): 
Download PDF

Subscribe to Ask Xmodulo

Do you want to receive Linux related questions & answers published at Ask Xmodulo? Enter your email address below, and we will deliver our Linux Q&A straight to your email box, for free. Delivery powered by Google Feedburner.


Support Xmodulo

Did you find this tutorial helpful? Then please be generous and support Xmodulo!

8 thoughts on “How to compare two version numbers in a shell script

  1. It would probably worth also adding -b to make sure that some extra leading blanks don't confuse sort.

  2. Why would you develop a version comparison? You can install rpmdevtools, and you then use the command:
    rpmdev-vercmp foo-2.1.0.010 foo-2.1.0.007

    With the output:
    0:foo-2.1.0.010 is newer
    https://fedoraproject.org/wiki/Rpmdevtools

    When you want this done in PHP there is a function called version_compare — Compares two "PHP-standardized" version number strings.
    php.net/manual/en/function.version-compare.php

  3. This method only works when the number of digits in each field is the same. It fails, for example, with 1.9 and 1.10. One really needs to break the version up into fields and compare them numerically. One could also rewrite each version so that each field has the same number of digits: 001.009 and 001.010. Then the method above would work. Perl makes such a rewrite easy:

    $ver=1.9
    $new_ver=`perl -e 's/\b\d\b/00$&/g;s/\b\d\d\b/0$&/g;print' $ver

    This gives "001.009".

    • And then I saw that -V does this type of sorting already. So the rewrite is only necessary if your version of sort (like mine) doesn't support -V.

  4. It does not treat, e.g., "0.9" and "0.9.0" as equivalent. The version_ge function says 0.9.0 is NOT greater than or equal to 0.9.

Leave a comment

Your email address will not be published. Required fields are marked *