The following is what I ended up using to reliably create a temporary directory that works on both Linux and Darwin (all versions before Mac OS X 10.11), without hardcoding $TMPDIR
or /tmp
:
mytmpdir=$(mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir')
Background:
The GNU mktemp command requires no arguments. Plain mktemp
will work and creates a temporary file in the system's temporary directory.
Plain mktemp -d
will create a directory instead of a file, which is what you'd want to use on Linux.
(gnu-coreutils)$ man mktemp
> ..
> If DIR is not specified, uses $TMPDIR if set, else /tmp.
> ..
By default, GNU mktemp uses the template tmp.XXXXXXXXXX
for the name of the sub directory (or file). To customise this template, the -t
option can be used.
OSX's mktemp has no default template and requires a template to be specified. Unfortunately, where GNU mktemp takes the template as -t
option, on OSX this is passed as positional argument. Instead, OSX's mktemp has a -t
option that means something else. The -t
option on OSX is documented as a "prefix" for the template. It is expanded to {prefix}.XXXXXXXX
, so it adds the Xs to it automatically (e.g. mktemp -d -t example
could create example.zEJZWCTQ
in the temp directory).
I was surprised to find that in many Linux environments, $TMPDIR
is not set by default. Many CLI programs do support it when set, but still need a default for /tmp
. This means passing $TMPDIR/example.XXXXXXXX
to mktemp or mkdir is dangerous because it may produce /example.XXXXXXXX
in the root directory of the local disk (due to $TMPDIR being unset and becoming an empty string).
On OSX, $TMPDIR
is always set and (at least in the default shell) it is not set to /tmp
(which is a symlink to /private/tmp
) but to /var/folders/dx/*****_*************/T
. So whatever we do for OSX, should honour that default behaviour.
In conclusion, the following is what I ended up using to reliably create a temporary directory that works on both Linux and Darwin (Mac OS X), without hardcoding either $TMPDIR
or /tmp
:
mytmpdir=$(mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir')
The first part is for Linux. This command will fail on Darwin (Mac OS X) with error status code 1
responding with "usage: ...". That's why we ignore stderr and instead then execute the Mac variant. The mytmpdir
prefix is only used on Mac (where that option is required to be set).