Finding the correct tmp dir on multiple platforms

A slightly more portable way to handle temporary files is to use mktemp. It'll create temporary files and return their paths for you. For instance:

$ mktemp
/tmp/tmp.zVNygt4o7P
$ ls /tmp/tmp.zVNygt4o7P
/tmp/tmp.zVNygt4o7P

You could use it in a script quite easily:

tmpfile=$(mktemp)
echo "Some temp. data..." > $tmpfile
rm $tmpfile

Reading the man page, you should be able to set options according to your needs. For instance:

  • -d creates a directory instead of a file.
  • -u generates a name, but does not create anything.

Using -u you could retrieve the temporary directory quite easily with...

$ tmpdir=$(dirname $(mktemp -u))

More information about mktemp is available here.

Edit regarding Mac OS X: I have never used a Mac OSX system, but according to a comment by Tyilo below, it seems like Mac OSX's mktemp requires you to provide a template (which is an optional argument on Linux). Quoting:

The template may be any file name with some number of "Xs" appended to it, for example /tmp/temp.XXXX. The trailing "Xs" are replaced with the current process number and/or a unique letter combination. The number of unique file names mktemp can return depends on the number of "Xs" provided; six "Xs" will result in mktemp selecting 1 of 56800235584 (62 ** 6) possible file names.

The man page also says that this implementation is inspired by the OpenBSD man page for mktemp. A similar divergence might therefore be observed by OpenBSD and FreeBSD users as well (see the History section).

Now, as you probably noticed, this requires you to specify a complete file path, including the temporary directory you are looking for in your question. This little problem can be handled using the -t switch. While this option seems to require an argument (prefix), it would appear that mktemp relies on $TMPDIR when necessary.

All in all, you should be able to get the same result as above using...

$ tmpdir=$(dirname $(mktemp tmp.XXXXXXXXXX -ut))

Any feedback from Mac OS X users would be greatly appreciated, as I am unable to test this solution myself.


If you're looking for the same thing in fewer lines...

for TMPDIR in "$TMPDIR" "$TMP" /var/tmp /tmp
do
    test -d "$TMPDIR" && break
done

You could write this in one.


You might do:

: "${TMPDIR:=${TMP:-$(CDPATH=/var:/; cd -P tmp)}}"
cd -- "${TMPDIR:?NO TEMP DIRECTORY FOUND!}" || exit

The shell should either find an executable directory in one of the 4 alternatives or exit with a meaningful error. Still, POSIX defines the $TMPDIR variable (for XCU systems):

TMPDIR This variable shall represent a pathname of a directory made available for programs that need a place to create temporary files.

It also requires the /tmp path.