I need to test if Bash version number is >= to a specific number. For example I have:
$ bash --version
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
In order to use associative arrays the bash version number must be >=4.
In my bash script I'd like to put in a one-liner test in the most elegant / efficient / readable way possible, but other approaches are also accepted.
Try:
BASH_VERSINFO
is a readonly array variable whose members hold version information for this instance of bash. Since it was introduced with bash 2.0, it is likely supported by all bash versions you will encounter. But, to be cautious, we include a default value of of0
for any earlier version bash for which this variable is unset.Extracting version information from other programs
You asked about LibreOffice, Python, kernel, etc.
LibreOffice produces version information that looks like:
To extract the version number:
For python:
To obtain the kernel version, use
uname
:Instead of comparing version numbers, you could test directly for the feature itself.
declare -A
returns2
(at least in Bash 3.2) if it doesn't recognize-A
, so test for that (it also prints an error):(
declare -A var
also fails ifvar
is a non-associative array, sounset
it first.)While I don't really assume anyone's going to backport features in Bash, in general it's more appropriate to check for the features, not the versions. Even in Bash's case, someone might compile a version with only limited features...
The more general case of testing version numbers has two parts: 1) how to find the correct version number to test, and 2) how to compare it against another value.
The first is the more difficult one. Many programs tell their version number with a command line flag like
--version
or-v
, but the output format varies and programmatically picking the version number may be difficult. Then there's the issue of possibly having several versions of the same program installed at the same time.The second depends on some knowledge of the format of the version numbers.
dpkg
can compare Debian-style version numbers (which I think includes semver type versions as subset):Or, just to combine the above:
There's couple ways to approach what you want to achieve.
1. Use $BASH_VERSION
It's sufficient to just to see what's in
$BASH_VERSION
variable. Personally I'd use subshell like so:Note that
<<<
syntax for here-doc is not portable, if you're going to use it with/bin/sh
, which is Dash on Ubuntu and might be something else on a different systemAlternative way is via case statement or if statement. Personally, I'd do this:
Probably for the sake of portability , you probably should check if such variable is even set at all in the first place with something like
[ -n $BASH_VERSION ]
This totally can be rewritten as function to be used in a script. Something a long the lines of:
This is not a one-liner, although this is much better. Quality over quantity.
2. Check what's installed
For that you need to filter output of
apt-cache policy
like sodpkg-query
can also come in handy with some filtering viaawk
.Note that this is not portable, since if there's no
dpkg
orapt
installed on a system ( for instance, RHEL or FreeBSD ), it won't do you any good.3. Use set -e to exit script if there's an error
One way to get around it is just simply go ahead an use associative arrays and quit when
bash
cannot use them.set -e
line below#!/bin/bash
will allow the script to quit if the script can't use associative array.This will require you to explicitly tell the user: "Hey, you really need bash version 4.3 or above, otherwise the script won't work". Then the responsibility rests with the user, although some might argue that this is not really a good approach to software development.
4. Abandon all hope and write portable, POSIX-compliant scripts
bash
scripts aren't portable because its syntax isn't compatible with Bourne shell. If the script that you're writing is going to be used on a range of different systems, not just Ubuntu alone, then abandon all hope, and find ways to use something other than associative arrays. That might include having two arrays or parsing a configuration file. Consider also switching to a different language, Perl or Python, where syntax is at least more portable thanbash
.One-liner not possible but a bash script is possible
I developed a script that draws on answers in Stack Overflow. One of those answers led to a Dell Employee writing version number comparisons in 2004 for the DKMS application.
The code
The bash script below needs to be marked as executable using the command
chmod a+x script-name
. I'm using the name/usr/local/bin/testver
: