Compare macOS Versions with zsh and is-at-least

Update (26 July 2020)

Howard Oakley has reported that Big Sur is both 10.16 and 11.0.

For the purposes of shells scripts, sw_vers will return 11.0 unless SYSTEM_VERSION_COMPAT=1 is set. If it is set, then sw_vers will return 10.16.

To my mind, this new information only makes the following suggestion more useful, because it will work under either scenario.

end of update

Original Post

I have already run into an issue where I’ve had to adapt some of my scripts for Big Sur.

(n.b. if you have used the -p arg to shasum in the past, it no longer exists in Big Sur. There is a new -U option which is not the same as what -p used to do. Ironically, -p was for ‘portable’ mode.)

It has already been noted that Apple is referring to Big Sur as “macOS 11” which presumably means that sw_vers -productVersion will return ‘11.0’ once Big Sur is out of beta.

However, at least as of this writing (10 July 2020), sw_vers -productVersion on Big Sur returns ‘10.16’.

If you are trying to write a shell script which can be used on both Big Sur and earlier versions of macOS, how can you check to see which version you are running?

I would like to recommend the following, which uses a feature which I believe is unique to zsh — and since Apple has made zsh it’s preferred shell, I recommend writing all of your shell scripts in zsh (however I should note that I may be a little biased, as I’ve been using zsh for 20+ years).

is-at-least

The zsh feature in question is called is-at-least and you use it like this:

autoload is-at-least

is-at-least "$MINIMUM" "$ACTUAL"

where $MINIMUM and $ACTUAL represent the two numbers that you want to compare. What is especially nice about is-at-least is that it can compare version numbers such as 10.15.5 and 10.13.4 and 10.16 (or 11.0).

Note: the autoload is-at-least line needs to be called once-per-script before you use is-at-least but once you’ve loaded it, you can use is-at-least as many times as you want in that script.

The key here is that regardless of whether Big Sur reports itself as 10.16 or 11.0, we can use ‘10.16’ as $MINIMUM and then set $ACTUAL to the version of macOS that we are using.

Note that you don’t have to use variables here, you could do this:

autoload is-at-least

is-at-least "10.16" "$ACTUAL"

The result of is-at-least will be zero if $ACTUAL is at least equal to 10.16, or 1 if it is not.

Here’s a complete example script as a gist for those who may find it useful.


#!/bin/zsh -f
# Purpose: Check to see if we are running on Big Sur
#
# From: Timothy J. Luoma
# Mail: luomat at gmail dot com
# Date: 2020-07-10
PATH="/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin"
# this will check to make sure `sw_vers` exists
# if it does not, this is probably not macOS
if ((! $+commands[sw_vers] ))
then
echo "$NAME: 'sw_vers' is required but not found in $PATH" >>/dev/stderr
exit 2
fi
## First we get the value for this Mac and save it to `$ACTUAL`
ACTUAL=$(sw_vers -productVersion)
## load 'is-at-least' so we can use it
autoload is-at-least
## "Is the version of macOS that we are using _at least_ 10.16?"
is-at-least "10.16" "$ACTUAL"
## EXIT will be '0' if ACTUAL is at least 10.16
## EXIT will be '1' if ACTUAL is _less than_ 10.16
EXIT="$?"
if [[ "$EXIT" == "0" ]]
then
# This is Big Sur (or later)
echo "YES"
elif [[ "$EXIT" == "1" ]]
then
# This is BEFORE Big Sur
echo "NO"
else
# we should never get here
echo "This should not have happened. EXIT = $EXIT"
fi
exit 0

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.