17612.4.9.1.8
cannot be considered as an integer. Not even as a number: too many dots. If you want to compare dot-separated versions you must do this one field at a time, starting from the major version number.
One option is to store the fields in an array:
$ m=(${monterey//./ })
$ echo ${m[0]}
17612
$ echo ${#m[@]}
5
m=(${monterey//./ })
replaces all dots in $monterey
by spaces and stores the result in array m
, one space-separated word per cell. ${#m[@]}
expands as the size of the array. So, something like the following should do what you want:
m=(${monterey//./ })
v=(${version//./ })
(( n = ${#v[@]} < ${#m[@]} ? ${#m[@]} : ${#v[@]} ))
for (( i=0; i < n; i++ )); do
if (( ${v[i]:-0} < ${m[i]:-0} )); then
echo "Needs update"
break
elif (( ${v[i]:-0} > ${m[i]:-0} )); then
echo "Up to date"
break
fi
done
exit 0
(( n = ${#v[@]} < ${#m[@]} ? ${#m[@]} : ${#v[@]} ))
stores the largest array size in variable n
. ${v[i]:-0}
expands as v[i]
if it is set and not the empty string, else as 0
.
But if you can use sort
, instead of plain bash
, you can also use:
l=$(printf '%s\n%s\n' "$monterey" "$version" | sort -nt. | tail -n1)
if [[ $version = $l ]]; then
echo "Up to date"
else
echo "Needs update"
fi
exit 0
The first command sorts the two versions numerically (-n
), using .
as separator (-t.
), keeps only the last (tail -n1
), that is, the largest, and stores it in variable l
. Note that this could not work as you would like if you can have trailing 0
fields: 1.2.0.0
will be considered as larger than 1.2.0
or 1.2
.
As mentioned by @markp-fuso, if your sort
utility supports it (it is a non-POSIX feature found, for instance, in the GNU coreutils sort
), you can also use its -V
option that does exactly what you want:
l=$(printf '%s\n%s\n' "$monterey" "$version" | sort -V | tail -n1)