#!/usr/bin/env bash # # Author: Georg Voell - georg.voell@standby.cloud # Version: @(#)compare-version 3.3.1 16.03.2026 (c)2026 Standby.cloud # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ # # This script can be used free of charge. Use it as is or customize as needed. It is not guaranteed to be # error free and you will not be reimbursed for any damage it may cause. # #@ Compare two version numbers e.g. 1.6.7 1.7.0 #@ Returns "older" if version in second parameter is older than version in first parameter. #@ Returns "newer" if version in second parameter is newer than version in first parameter. #@ Returns "same" if both versions are the same. #@ #@Usage: compare-version [options] versionnumber versionnumber #@ Options: #@ -h, --help : Displays helptext. #@ -v, --version : Displays the version of the script. #@ -q, --quiet : Don't display any error messages. #@ VersionNumber: e.g. 1.2.5 #@ #@Examples: #@ compare-version 1.2.4 1.2.5 #@ Returns "newer" #@ compare-version 1.2 1.2.5 #@ Returns "same" - only first two letters will be compared. # # Exit codes: # 01: Unknown or wrong parameter. # 02: Not a number. # # Update history: # # V 3.0.0 18.04.2020 New version # V 3.0.1 11.06.2020 Using library # V 3.0.2 10.11.2022 Silent mode # V 3.1.0 05.06.2023 New copyright # V 3.2.0 11.09.2024 New minor version # V 3.3.0 19.01.2026 Revised with support of Claude Code # V 3.3.1 16.03.2026 Optimized: replaced backticks with $(); [ ] with [[ ]]; # echo|grep with bash regex [[ =~ ]]; echo with printf # # Find executable bash library and source it lib=$(command -v lib.bash 2>/dev/null) if [[ -n "$lib" ]]; then source "$lib" else progdir=$(dirname "$0") if [[ -r "${progdir}/lib.bash" ]]; then source "${progdir}/lib.bash" else echo "Unexpected error: Unable to locate bash library 'lib.bash'." exit 1 fi fi function compare() { local a="${1}" local b="${2}" # Use bash regex instead of echo|grep subshell if [[ ! "$a" =~ ^[0-9]+$ ]]; then exitcode=2 errormsg $quietstr $exitcode "($progstr) Not a number: '$a'." return $exitcode fi if [[ ! "$b" =~ ^[0-9]+$ ]]; then exitcode=2 errormsg $quietstr $exitcode "($progstr) Not a number: '$b'." return $exitcode fi if (( a == b )); then printf 'same\n' elif (( a > b )); then printf 'older\n' else printf 'newer\n' fi } function split() { local a="${1}" # Use bash parameter expansion instead of grep+cut subshells if [[ "$a" == *.* ]]; then printf '%s\n' "${a%%.*}" else printf '%s\n' "$a" fi } function check() { local par1 local par2 local res par1=$(split "$param1") par2=$(split "$param2") res=$(compare "$par1" "$par2") local stat=$? if [[ $stat -eq 0 ]]; then if [[ "$res" == "same" ]]; then # Strip leading segment (bash built-in, no sed subshell) param1="${param1#${par1}.}" param2="${param2#${par2}.}" if [[ -n "$param1" && -n "$param2" ]]; then res=$(check) stat=$? if [[ $stat -eq 0 ]]; then printf '%s\n' "$res" fi else printf 'same\n' fi else printf '%s\n' "$res" fi fi return $stat } # Preset param1="" param2="" quietstr="" # Check parameters: Loop until all parameters are used up while [[ $# -gt 0 ]]; do pname="${1}" case "$pname" in -v | --version) shift showversion=true ;; -h | --help) shift showhelp=true ;; -q | --quiet) shift quietstr="$pname" ;; *) shift # Use bash pattern match instead of echo|grep subshell if [[ "$pname" == -* ]]; then errstr="Unknown option '$pname'." else if [[ -z "$param1" ]]; then # Append dot and squeeze duplicates with bash built-in tmp="${pname}." param1="${tmp//../.}" elif [[ -z "$param2" ]]; then tmp="${pname}." param2="${tmp//../.}" else errstr="Versions were already specified '$param1 $param2'. Unknown additional parameter: '$pname'." fi fi ;; esac done # Plausibility check if [[ -z "$param2" ]]; then errstr="You have to compare two version numbers (e.g. 1.2.5) to get a result." fi # Display help or error message DisplayHelp # Compare if [[ "$param1" == "$param2" ]]; then printf 'same\n' else result=$(check) exitcode=$? if [[ $exitcode -eq 0 ]]; then printf '%s\n' "$result" fi fi exit $exitcode