How to compare a program's version in a shell script?

36,070

Solution 1

I don't know if it is beautiful, but it is working for every version format I know.

#!/bin/bash
currentver="$(gcc -dumpversion)"
requiredver="5.0.0"
 if [ "$(printf '%s\n' "$requiredver" "$currentver" | sort -V | head -n1)" = "$requiredver" ]; then 
        echo "Greater than or equal to ${requiredver}"
 else
        echo "Less than ${requiredver}"
 fi

(Note: better version by the user 'wildcard': https://unix.stackexchange.com/users/135943/wildcard , removed additional condition)

Solution 2

Shorter version:

version_greater_equal()
{
    printf '%s\n%s\n' "$2" "$1" | sort --check=quiet --version-sort
}

version_greater_equal "${gcc_version}" 8.2 || die "need 8.2 or above"

Solution 3

function version_compare () {
  function sub_ver () {
    local len=${#1}
    temp=${1%%"."*} && indexOf=`echo ${1%%"."*} | echo ${#temp}`
    echo -e "${1:0:indexOf}"
  }
  function cut_dot () {
    local offset=${#1}
    local length=${#2}
    echo -e "${2:((++offset)):length}"
  }
  if [ -z "$1" ] || [ -z "$2" ]; then
    echo "=" && exit 0
  fi
  local v1=`echo -e "${1}" | tr -d '[[:space:]]'`
  local v2=`echo -e "${2}" | tr -d '[[:space:]]'`
  local v1_sub=`sub_ver $v1`
  local v2_sub=`sub_ver $v2`
  if (( v1_sub > v2_sub )); then
    echo ">"
  elif (( v1_sub < v2_sub )); then
    echo "<"
  else
    version_compare `cut_dot $v1_sub $v1` `cut_dot $v2_sub $v2`
  fi
}

### Usage:

version_compare "1.2.3" "1.2.4"
# Output: <

Credit goes to @Shellman

Solution 4

Here I give a solution for comparing Unix Kernel versions. And it should work for others such as gcc. I only care for the first 2 version number but you can add another layer of logic. It is one liner and I wrote it in multiple line for understanding.

check_linux_version() {
    version_good=$(uname -r | awk 'BEGIN{ FS="."}; 
    { if ($1 < 4) { print "N"; } 
      else if ($1 == 4) { 
          if ($2 < 4) { print "N"; } 
          else { print "Y"; } 
      } 
      else { print "Y"; }
    }')

    #if [ "$current" \< "$expected" ]; then
    if [ "$version_good" = "N" ]; then
        current=$(uname -r)
        echo current linux version too low
        echo current Linux: $current
        echo required 4.4 minimum
        return 1
    fi
}

You can modify this and use it for gcc version checking.

Solution 5

With lastversion CLI utility you can compare any arbitrary versions, e.g.:

#> lastversion 1.0.0 -gt 0.9.9
#> 1.0.0

Exit code 0 when "greater" condition is satisfied.

Share:
36,070

Related videos on Youtube

Amoon3234
Author by

Amoon3234

Updated on September 18, 2022

Comments

  • Amoon3234
    Amoon3234 almost 2 years

    Suppose I want to compare gcc version to see whether the system has the minimum version installed or not.

    To check the gcc version, I executed the following

    gcc --version | head -n1 | cut -d" " -f4
    

    The output was

    4.8.5
    

    So, I wrote a simple if statement to check this version against some other value

    if [ "$(gcc --version | head -n1 | cut -d" " -f4)" -lt 5.0.0 ]; then
        echo "Less than 5.0.0"
    else
        echo "Greater than 5.0.0"
    fi
    

    But it throws an error:

    [: integer expression expected: 4.8.5
    

    I understood my mistake that I was using strings to compare and the -lt requires integer. So, is there any other way to compare the versions?

    • Amoon3234
      Amoon3234 about 8 years
      @123 Nothing happens
    • n.st
      n.st about 8 years
      There's also a Stack Overflow question with a bunch of different suggestions for comparing version strings.
    • Victor Lamoine
      Victor Lamoine over 7 years
      Much simpler than using pipes: gcc -dumpversion
  • Mathias Begert
    Mathias Begert about 8 years
    or you could use sort's own checking facilities if printf '%s\n%s\n' "$(gcc --version | head -n1 | awk '{print $NF}')" 5.0.0 | sort -cV; then echo 'less'; else echo 'more'; fi - admittedly less readable
  • Larry Hosken
    Larry Hosken about 8 years
    At first I thought this was awful, and then I realized the beauty of shell scripting is precisely in abusing tools like this. +1
  • phk
    phk over 7 years
    This breaks if there are '%' signs in the print statement. Better replace printf "$requiredver\n$currentver" with printf '%s\n' "$requiredver" "$currentver".
  • Wildcard
    Wildcard over 6 years
    @LucianoAndressMartini, see what you think of my edit.
  • Luciano Andress Martini
    Luciano Andress Martini over 6 years
    I am reading it. Looks great! It is better now, do you want to make it the official version and remove the other form?
  • Luciano Andress Martini
    Luciano Andress Martini over 6 years
    +1 it is compatible with other Unix-like ? (My solution is not)
  • G-Man Says 'Reinstate Monica'
    G-Man Says 'Reinstate Monica' over 4 years
    (1) This is a minor variation of already-given answers.  You could add value by adding an explanation, which has not yet been posted.  (2) printf '%s\n' is good enough; printf will repeat the format string as needed.
  • Gaojin
    Gaojin over 4 years
    I normally prefer editing existing answers but deleting half of them is tricky: others may see value where I don't. Same for verbose explanations. Less is more.
  • Gaojin
    Gaojin over 4 years
    I know that printf repeats the format string but I the (lack of!) syntax for this is IMHO obscure; so I use this only when required = when the number of arguments is large or variable.
  • Brad Parks
    Brad Parks about 4 years
    Nice! This works and is super easy to extend, and very portable!
  • MaXi32
    MaXi32 almost 3 years
    This is the best solution!