Testing the OS Version on Darwin/Mac OS X in bash ¬

2008-08-14

I’ve been updating an installer bash script that needs to install different files depending on the version of Mac OS X (and Darwin, for that matter) that the machine is running and so set out to find the easiest, most straightforward way to check the OS version.

Of course, the hostinfo command shows you most of the juicy details one would need, but it’s not worth trying to parse it. sysctl lets you query various kernel states, including the OS release version:

sysctl -n kern.osrelease

Which will spit back something like the following (on Mac OS X 10.5.4, in this example):

9.4.0

This is the Darwin release number. To convert a darwin release version number to a Mac OS X version number just subtract 4 from the major revision (9, in this case) and then prepend the ’10.’ to the entire thing. So, 9.4.0 becomes 10.5.4.0.

You can also use uname -r to get the OS release version, but I’m going to stick with sysctl for now.

Of course, you can’t do a direct comparison, so you’ll want to compare either the major or the minor revision (the last release field is always zero, so it can be ignored). The easiest way to do that is to pipe the output from sysctl through the cut command.

The following will give you the major release number (again, 9, in this case):

sysctl -n kern.osrelease | cut -d . -f 1

It cuts the output of sysctl on the ‘.’ delimiter and returns the first field. We can return the second field (the minor revision; 4, in our example) like so:

sysctl -n kern.osrelease | cut -d . -f 2

In my script, I simply needed to test if the machine was running Tiger or earlier, or Leopard or newer. Here’s a quick example of getting that functionality:

#!/bin/bash
if [ `sysctl -n kern.osrelease | cut -d . -f 1` -lt 9 ]; then
	echo "Tiger or earlier"
else
	echo "Leopard or newer"
fi

If you’re doing something more advanced, it might be easier to set variables first:

darwinos_major=`sysctl -n kern.osrelease | cut -d . -f 1`
darwinos_minor=`sysctl -n kern.osrelease | cut -d . -f 2`

Then just reference $darwinos_major & $darwinos_minor whenever needed.

  1. You could also use the sw_vers command if you only need the Mac OS X info.

  2. True, I hadn’t noticed that. One could definitely use sw_vers -productVersion in place of sysctl -n kern.osrelease (although you’d still want to use cut if trying to differentiate between major and minor release numbers).

  Textile help