forked from j1elo/shell-snippets
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommand-version-check.sh
executable file
·87 lines (68 loc) · 2.96 KB
/
command-version-check.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/usr/bin/env bash
# Snippet: Check if a command is installed and if its version is high enough.
# Bash options for strict error checking
set -o errexit -o errtrace -o pipefail -o nounset
shopt -s inherit_errexit 2>/dev/null || true
# Self path
SELF_FILE="$(basename "${BASH_SOURCE[0]}")" # File name
# Log function
# This disables and re-enables debug trace mode, only if it was already set
# Source: https://superuser.com/a/1338887/922762
shopt -s expand_aliases # This trick requires enabling aliases in Bash
echo_and_restore() {
echo "[$SELF_FILE] $(cat -)" >&2
# shellcheck disable=SC2154
case "$flags" in (*x*) set -x; esac
}
alias log='({ flags="$-"; set +x; } 2>/dev/null; echo_and_restore) <<<'
# Trace all commands
set -o xtrace
# Settings
# ========
# This could be a real use case for the commands shown here:
#
# COMMAND="clang"
# COMMAND_ARG="--version"
# VERSION_REQ="9.0.1"
# However for demonstration purposes, and in order to not depend on Clang,
# we'll use dummy strings that prove how the version extraction works.
#
COMMAND="echo"
# COMMAND_ARG="This is version 111.222ABC -- More text"
COMMAND_ARG="This is version 111.221.333ABC -> More text"
# COMMAND_ARG="This is version 111.222.333.4.5 (More text)"
VERSION_REQ="111.222.0"
# Check if the requested command is installed and available in the environment
if ! command -v "$COMMAND" >/dev/null; then
log "Command '$COMMAND' is not installed in the system"
exit 1
fi
# Get the command output
COMMAND_STR="$("$COMMAND" "$COMMAND_ARG")"
log "Command output (raw string): '$COMMAND_STR'"
# Parse the program version number.
# Note that in this regex, we let the PATCH number to be optional.
# So, the program version might be "1.2" or "1.2.3".
# This can be important, depending on the kind of processing to be done later.
VERSION_STR="$(echo "$COMMAND_STR" | grep -Po '(\d+\.\d+(\.\d+)?)' | head -1)"
# An alternative with Perl (which is anyway installed in most systems)
# VERSION_STR="$(echo "$COMMAND_STR" | perl -ne '/(\d+\.\d+(\.\d+)?)/ && print $1')"
log "Command version (parsed): '$VERSION_STR'"
# (Optional) Break the version into its individual components
VERSION_MAJ="$(echo "$VERSION_STR" | cut -d. -f1)"
VERSION_MIN="$(echo "$VERSION_STR" | cut -d. -f2)"
VERSION_FIX="$(echo "$VERSION_STR" | cut -d. -f3)"
VERSION_FIX="${VERSION_FIX:-0}" # IN this example, Patch is optional so maybe there was none.
log "Version components: '$VERSION_MAJ', '$VERSION_MIN', '$VERSION_FIX'"
# This function returns an integer number which has filled in all its possible
# version components (Major.Minor.Patch.Other), up to a maximum of 4.
# E.g. it converts a component of "1" into "001", or "0" into "000".
function version_int {
echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'
}
if [[ $(version_int "$VERSION_STR") -ge $(version_int "$VERSION_REQ") ]]; then
log "Version '$VERSION_STR' >= '$VERSION_REQ', all OK"
else
log "Version '$VERSION_STR' < '$VERSION_REQ', NOT OK"
fi
log "Done!"