29

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?

3
  • @123 Nothing happens May 27, 2016 at 14:21
  • 1
    There's also a Stack Overflow question with a bunch of different suggestions for comparing version strings.
    – n.st
    May 29, 2016 at 3:31
  • 1
    Much simpler than using pipes: gcc -dumpversion Jan 4, 2017 at 14:18

6 Answers 6

48

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)

9
  • 8
    At first I thought this was awful, and then I realized the beauty of shell scripting is precisely in abusing tools like this. +1 May 27, 2016 at 23:52
  • 3
    This breaks if there are '%' signs in the print statement. Better replace printf "$requiredver\n$currentver" with printf '%s\n' "$requiredver" "$currentver".
    – phk
    Nov 5, 2016 at 10:50
  • 1
    -V is a GNU extension of sort(1) thus this solution is non-portable.
    – stefanct
    Sep 4, 2017 at 0:46
  • 1
    sort -n works pretty much the same way in case of numeral versions.
    – Rockallite
    Nov 22, 2017 at 7:22
  • 1
    @LucianoAndressMartini, see what you think of my edit.
    – Wildcard
    Jan 22, 2018 at 23:28
13

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"
4
  • (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. Feb 14, 2020 at 8:25
  • 1
    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.
    – MarcH
    Feb 18, 2020 at 19:56
  • 1
    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.
    – MarcH
    Feb 18, 2020 at 19:59
  • 1
    This is the best solution!
    – MaXi32
    Aug 26, 2021 at 6:11
2

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.

1
  • +1 it is compatible with other Unix-like ? (My solution is not) Feb 28, 2018 at 18:44
2
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

1

We used to do a lot of version checking in a GNU makefile. We shelled out through the makefile facilities. We had to detect old Binutils and buggy compilers and workaround them on the fly.

The pattern we used was:

#!/usr/bin/env bash

CC=$(command -v gcc)
GREP=$(command -v grep)

# Fixup CC and GREP as needed. It may be needed on AIX, BSDs, and Solaris
if [[ -f "/usr/gnu/bin/grep" ]]; then
    GREP="/usr/gnu/bin/grep"
elif [[ -f "/usr/linux/bin/grep" ]]; then
    GREP="/usr/linux/bin/grep"
elif [[ -f "/usr/xpg4/bin/grep" ]]; then
    GREP="/usr/xpg4/bin/grep"
fi

# Check compiler for GCC 4.8 or later
GCC48_OR_LATER=$("$CXX" -v 2>&1 | "$GREP" -i -c -E "gcc version (4\.[8-9]|[5-9]\.)")
if [[ "$GCC48_OR_LATER" -ne 0 ]];
then
   ...
fi

# Check assembler for GAS 2.19 or later
GAS219_OR_LATER=$("$CXX" -xc -c /dev/null -Wa,-v -o/dev/null 2>&1 | "$GREP" -c -E "GNU assembler version (2\.19|2\.[2-9]|[3-9])")
if [[ "$GAS219_OR_LATER" -ne 0 ]];
then
   ...
fi
2
  • Nice! This works and is super easy to extend, and very portable!
    – Brad Parks
    Apr 22, 2020 at 16:19
  • ""$GREP" -i -c -E "gcc version (4\.[8-9]|[5-9]\.)")" This fails for gcc >=10 (the current version is 11.1.0). I think it might be more future-proof to check if it's lesser than 4.8 instead. But as a simple fix, the following should probably work for any future major versions (e.g.: 999): "$GREP" -i -c -E "gcc version (4\.[8-9]|[5-9]\.|[1-9][0-9]*\.)"). The same issue might affect the GAS check at some point in the future.
    – kelvin
    Jun 18, 2021 at 11:33
1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.