Compairing version numbers

There are differences between versions of some of the relatively common utilities that occasionally make it necessary to check which version is installed in a script, but comparing version numbers in a script is quite hard – fortunately if you use Debian there is are a couple of commands that let you do this.

Getting the version number

I remembered that ‘dpkg-query’ will tell you all you ever wanted to know about a package.

$ dpkg-query -s bash
Package: bash
Essential: yes
Status: install ok installed
Priority: required
Section: shells
Installed-Size: 5010
Maintainer: Matthias Klose <doko@debian.org>
Architecture: amd64
Multi-Arch: foreign
Version: 4.3-11+deb8u1
Replaces: bash-completion (<< 20060301-0), bash-doc (<= 2.05-1)
Depends: base-files (>= 2.1.12), debianutils (>= 2.15)
Pre-Depends: dash (>= 0.5.5.1-2.2), libc6 (>= 2.15), libncurses5 (>= 5.5-5~), libtinfo5
Recommends: bash-completion (>= 20060301-0)
Suggests: bash-doc
Conflicts: bash-completion (<< 20060301-0)
Conffiles:
 /etc/bash.bashrc 87b895cef45b8090d628a1d9a0f4bfb8
 /etc/skel/.bash_logout 22bfb8c1dd94b5f3813a2b25da67463f
 /etc/skel/.bashrc e62ae447bdd228160f1f0b6bab8a7fd3
 /etc/skel/.profile ecb6d3479ac3823f1da7f314d871989b
Description: GNU Bourne Again SHell
 Bash is an sh-compatible command language interpreter that executes
 commands read from the standard input or from a file. Bash also
 incorporates useful features from the Korn and C shells (ksh and csh).
 
 Bash is ultimately intended to be a conformant implementation of the
 IEEE POSIX Shell and Tools specification (IEEE Working Group 1003.2).
 
 The Programmable Completion Code, by Ian Macdonald, is now found in
 the bash-completion package.
$

Somewhere in there is the version number, but the question is how to extract it.

Looking through the man pages I spotted the following section:

# man dpkg-query
  :
  :
  :
    -f, --showformat=format
         This option is used to specify the format of the output --show
         will  produce.  The format is a string that will be output for
         each package listed..
          In the format string, "\" introduces escapes:

              \n  newline
              \r  carriage return
              \t  tab

          "\" before any other character suppresses any special  meaning
          of the following character, which is useful for "\" and "$".

          Package information can be included by inserting variable ref‐
          erences to package fields using the syntax "${field[;width]}".
  :
  :
  :
$

This is followed by a long list of fields that can be used, one of which is the package version.

$ dpkg-query -f='${Version}\n' --show bash
4.3-11+deb8u1
#

Comparing version numbers

Again the the man pages are your friend.

$ man dpkg
  :
  :
  :
    --compare-versions ver1 op ver2
         Compare  version  numbers, where op is a binary operator. dpkg
         returns success (zero result) if the  specified  condition  is
         satisfied,  and  failure (nonzero result) otherwise. There are
         two groups of operators, which differ in  how  they  treat  an
         empty  ver1  or  ver2. These treat an empty version as earlier
         than any version: lt le eq ne ge gt. These treat an empty ver‐
         sion as later than any version: lt-nl le-nl ge-nl gt-nl. These
         are provided only for compatibility with control file  syntax:
         < << <= = >= >> >.
:
:
:
$

Great but that does this mean?

Essentially we can use ‘dpkg’ to compare two version numbers and if the condition is true the status code returned by ‘dpkg’ will be zero (indicating success). So we use this command in an ‘if’ statement to compare version numbers.

Note – The arguments do not have to be enclosed in quotes, and the version numbers do not need to be numeric, though they must start with a digit (leading zeros are truncated) and they don’t have to be package versions.

$ if $(dpkg --compare-versions "2.11" "lt" "3"); then echo true; fi
true
$ if $(dpkg --compare-versions "0A.3" "lt" "000B"); then echo true; fi
true
$ if $(dpkg --compare-versions "2.11.e1" "lt" "2.12"); then echo true; fi
true
$ if $(dpkg --compare-versions 4.3-11+deb8u1 gt "4.3-11"); then echo true; fi
true
$ if $(dpkg --compare-versions 4.3-11+deb8u1 lt 4.3-12); then echo true; fi
true
$

By combining the ability to compare version numbers with the ability to obtain the version number of an installed package allows us to check the minimum version of any installed package …

$ if $(dpkg --compare-versions \
> $(dpkg-query -f='${Version}' --show bash) gt 3.2-3); \
> then echo yes ; else echo no; fi
yes
$

Advertisements
This entry was posted in Debian, Raspbian, Ubuntu and tagged , . Bookmark the permalink.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s