stwalkerster
stwalkerster

Reputation: 1808

How to get the Bash version number

I'm writing a script which requires the Bash version number in a simple short format.

I'm aware of bash --version, but this gives a long output:

GNU bash, version 4.2.10(1)-release (i686-pc-linux-gnu)
Copyright (C) 2011 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.

This could be cut down to the bit I want, 4.2.10, by this:

bash --version | grep "bash" | cut -f 4 -d " " | cut -d "-" -f 1  | cut -d "(" -f 1

However, this feels like it would be prone to break if that message ever changed slightly for whatever reason.

Is there a better way to do this, and what is this better way?

Upvotes: 39

Views: 27175

Answers (8)

Edouard Thiel
Edouard Thiel

Reputation: 6228

This is a variation of other responses with BASH_VERSINFO:

check_bash_version()
{
    local a=4 b=3   # Bash version >= a.b

    (( BASH_VERSINFO[0] > a || \
      (BASH_VERSINFO[0] == a && BASH_VERSINFO[1] >= b) )) || {
        echo "Error: Bash version >= $a.$b expected." >&2
        return 1
    }
}

check_bash_version || exit 1

Upvotes: 0

codeforester
codeforester

Reputation: 42999

Building more on FelixEnescu's great answer, here is a function that checks for just the major version or a combination of major and minor versions and returns 0 if the current Bash version is >= the needed version:

check_bash_version() {
    local major=${1:-4}
    local minor=$2
    local rc=0
    local num_re='^[0-9]+$'

    if [[ ! $major =~ $num_re ]] || [[ $minor && ! $minor =~ $num_re ]]; then
        printf '%s\n' "ERROR: version numbers should be numeric"
        return 1
    fi
    if [[ $minor ]]; then
        local bv=${BASH_VERSINFO[0]}${BASH_VERSINFO[1]}
        local vstring=$major.$minor
        local vnum=$major$minor
    else
        local bv=${BASH_VERSINFO[0]}
        local vstring=$major
        local vnum=$major
    fi
    ((bv < vnum)) && {
        printf '%s\n' "ERROR: Need Bash version $vstring or above, your version is ${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}"
        rc=1
    }
    return $rc
}

It can be invoked as:

check_bash_version 4   # Check if 4.0 or above
check_bash_version 4 2 # Check if 4.2 or above

See the assertion related to this:

https://github.com/codeforester/base/blob/f230fbacbb1d9fe48d68ce9302902fe2d3785dde/lib/assertions.sh#L12

Upvotes: 2

user7040344
user7040344

Reputation:

Run bash --version and then its output is like:

GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)

or

GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)

or

GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu)

Use Bash variable $BASH_VERSION and run echo $BASH_VERSION. Its output is like:

4.3.30(1)-release

Usually I use command sed to extract the version number, the following is the concrete command:

bash --version | sed -r -n 's@.*version (.*)\(1\)-release.*@\1@p'

For example:

[flying@lempstacker ~]$ bash --version | sed -r -n 's@.*version (.*)\(1\)-release.*@\1@p'
4.2.46
[flying@lempstacker ~]$
echo $BASH_VERSION | sed -r -n 's@(.*)\(1\)-release.*@\1@p'

For example:

[flying@lempstacker ~]$ echo $BASH_VERSION | sed -r -n 's@(.*)\(1\)-release.*@\1@p'
4.2.46
[flying@lempstacker ~]$

Upvotes: 1

FelixEnescu
FelixEnescu

Reputation: 5102

There's also a special array (BASH_VERSINFO) containing each version number in separate elements.

if ((BASH_VERSINFO[0] < 3))
then
  echo "Sorry, you need at least bash-3.0 to run this script."
  exit 1
fi

See 9.1. Internal Variables for more information:

# Bash version information:

for n in 0 1 2 3 4 5
do
  echo "BASH_VERSINFO[$n] = ${BASH_VERSINFO[$n]}"
done

# BASH_VERSINFO[0] = 3                      # Major version no.
# BASH_VERSINFO[1] = 00                     # Minor version no.
# BASH_VERSINFO[2] = 14                     # Patch level.
# BASH_VERSINFO[3] = 1                      # Build version.
# BASH_VERSINFO[4] = release                # Release status.
# BASH_VERSINFO[5] = i386-redhat-linux-gnu  # Architecture
                                            # (same as $MACHTYPE).

Upvotes: 44

Mansoor Siddiqui
Mansoor Siddiqui

Reputation: 21663

If you're running within a Bash shell, then the $BASH_VERSION environment variable should be set:

$ echo $BASH_VERSION
4.2.8(1)-release

That should be easier and more reliable to parse. See the man page for a list of environment variables set by the shell.

Upvotes: 37

mklement0
mklement0

Reputation: 438083

Building on FelixEnescu's helpful answer:

To report the first 3 version-number components - e.g., 4.2.10 - via built-in array shell variable BASH_VERSINFO:

$ bash -c 'IFS=.; echo "${BASH_VERSINFO[*]: 0:3}"'
4.2.10

If you're calling this from inside a Bash script, use a subshell in order to localize the effect of changing IFS:

#!/usr/bin/env bash

ver=$(IFS=.; echo "${BASH_VERSINFO[*]: 0:3}")  # -> e.g., $ver == '4.2.10'

Explanation:

  • IFS=. sets the internal field separator to ., which ensures that when we print an array inside a double-quoted string later, the array's elements are joined with that separator.

    • Note that you can't just do IFS=. echo ... to transiently redefine IFS scoped to the the echo command, because shell parameter expansion (the expansion of ${BASH_VERSINFO[*]: 0:3}, in this case) happens before echo is invoked. Therefore, two separate command are needed; the use of a command substitution ($(...)) ensures that the change to IFS is still localized, because command substitutions run in subshells.
  • ${BASH_VERSINFO[*]: 0:3} extracts the first 3 elements from array variable $BASH_VERSINFO (starting at index 0, return 3 elements).

    • Note that in order for IFS to work as intended, * rather than @ must be used to reference the array; @ would invariably separate the elements with a single space each, irrespective of the value of $IFS.

Upvotes: 2

kev
kev

Reputation: 161694

To extract the first part:

$ echo ${BASH_VERSION%%[^0-9.]*}
4.2.10

Upvotes: 11

jogojapan
jogojapan

Reputation: 69977

There seems to be an environment variable for this:

echo $BASH_VERSION

yields

4.1.7(1)-release

on my machine.

Upvotes: 4

Related Questions