I have a script that needs to create temporary files for its work, and clean up after itself. My question is about finding the right base directory for the temporary files.
The script needs to work on multiple platforms: Git Bash (Windows), Solaris, Linux, OSX.
On each platform, the preferred temp directory is expressed differently:
- Windows:
%TMP%(and possibly%TEMP%) - OSX:
$TMPDIR - Linux, UNIX: supposed to be
$TMPDIRbut appears to be unset on multiple systems I tried
So in my script I added this boilerplate:
if test -d "$TMPDIR"; then
:
elif test -d "$TMP"; then
TMPDIR=$TMP
elif test -d /var/tmp; then
TMPDIR=/var/tmp
else
TMPDIR=/tmp
fi
This seems too tedious. Is there a better way?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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:
-dcreates a directory instead of a file.-ugenerates 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.
Method 2
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.
Method 3
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):
TMPDIRThis 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.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0