19

I heard about $TEMP and $TMP, but I think they are not standard for every distro.

As far as I know, the best way to get the temp dir is just /tmp, is there any distro that won't work using that path?

3 Answers3

29

$TMPDIR is more standard than both $TEMP and $TMP as it's mentioned by the POSIX standard.

The /tmp directory is retained in POSIX.1-2008 to accommodate historical applications that assume its availability. Implementations are encouraged to provide suitable directory names in the environment variable TMPDIR and applications are encouraged to use the contents of TMPDIR for creating temporary files.

Ref: http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap10.html

At least on macOS, $TMPDIR is not set to /tmp by default, but to something like /var/folders/4r/504v61kx02gczk_454db345c0000gn/T/. /tmp is still available though, as a symbolic link to /private/tmp (for whatever reason).

You may use tmpdir="${TMPDIR:-/tmp}" in a script, for example, to use $TMPDIR if it's set, or /tmp if it's not set (or empty).

The non-standard mktemp utility will create a file or directory in $TMPDIR by default and output its name (but not on macOS, see below):

tmpfile=$(mktemp)
tmpdir=$(mktemp -d)

Check the manual for mktemp on your system to figure out how to use it. Not all implementations are the same.


On macOS, because of reasons, you will have to give the mktemp utility a template with an explicit path:

tmpfile=$(mktemp "${TMPDIR:-/tmp}"/tmp.XXXXXXXX)
tmpdir=$(mktemp -d "${TMPDIR:-/tmp}"/tmp.XXXXXXXX)

The above commands would create a temporary file and directory (respectively) in $TMPDIR, or in /tmp if $TMPDIR is empty or if the variable is unset (this variable is by default set to the result of getconf DARWIN_USER_TEMP_DIR on macOS).


On Cygwin, $TMPDIR is not set by default:

$ echo $TMPDIR

$ echo $TEMP /tmp

$ echo $TMP /tmp

Consider using ${TMPDIR:-${TEMP:-${TMP:-/tmp}}} instead.

Dave Jarvis
  • 211
  • 2
  • 9
Kusalananda
  • 333,661
  • Yes, you beat me by seconds. $TMPDIR is far more known than $TEMP or $TMP – Rui F Ribeiro Mar 17 '17 at 13:29
  • it's encouraged, not mandatory. So it's more standard than those variables. Just using /tmp, it's guaranteed. – cuonglm Mar 17 '17 at 13:31
  • @cuonglm ... but bad practice as it doesn't allow the user of the script to specify an alternative directory. I may, for example, want to use $HOME/tmp or /var/tmp for a particular run for the script. – Kusalananda Mar 17 '17 at 13:32
  • @cuonglm ${TMPDIR:-/tmp}. Setting TMPDIR is way to tell applications to use a different area than /tmp for temp files. Most applications honour it. It's good practice to honour it (place temp files there as and when requested by the user with that $TMPDIR variable instead of /tmp) unless there are security implications (like for setuid applications) – Stéphane Chazelas Mar 17 '17 at 13:35
  • @StéphaneChazelas: Yes, sure. I mean in term of standard, TMPDIR is no more standard than TEMP or TMP. – cuonglm Mar 17 '17 at 13:41
  • 5
    @cuonglm What? POSIX says (of its standard utilities) “If applications are written to use temporary or intermediate files, they should use the TMPDIR environment variable, if it is set and represents an accessible directory, to select the location of temporary files.” How is that not standard? – Stephen Kitt Mar 17 '17 at 13:48
  • @StephenKitt: I remember it said encouraged, not should. – cuonglm Mar 17 '17 at 13:54
  • 2
    @cuonglm that’s a direct copy/paste from the standard. – Stephen Kitt Mar 17 '17 at 13:59
  • @StephenKitt Well, thanks. I'm not aware that part of document. – cuonglm Mar 17 '17 at 14:02
  • 2
    nitpick: ${TMPDIR:-/tmp} would still be expanded to /tmp if $TMPDIR was set but to the empty string. One might argue that an empty $TMPDIR could be regarded as meaning the current directory, but IMO, it's better to consider an empty $TMPDIR as if it was unset and force users to specify the current directory with TMPDIR=., and that avoids having to do things like ${TMPDIR-/tmp}${TMPDIR:+/}file.tmp.$$ – Stéphane Chazelas Mar 17 '17 at 14:07
  • Note that there are various variants of a mktemp command. Some require a /tmp/prefixXXXX template argument. Not all support -d IIRC. – Stéphane Chazelas Mar 17 '17 at 14:12
  • 1
    See also echo 'mkstemp(TEMPLATE)' | m4 -D TEMPLATE="${TMPDIR:-/tmp}/prefixXXXXXX" for a standard way to create a temp file. – Stéphane Chazelas Mar 17 '17 at 14:26
  • just my 2c - As a sysadm who sees this issue a lot - its nice to prefix the tmp file/dir with the name of the script that created it, so if it doesn't clean up after itself, you know what script needs fixing - maybe something like -> tmpdir=$(mktemp -d "${TMPDIR:-/tmp}/$(basename $0)".XXXXXXXX) – James Stevens Nov 10 '23 at 11:54
3

NOTE: The OPs question is "Generic way to get temp path?"; it is not "How to create a temp file/dir?"

The Linux man page for mktemp includes these options:

mktemp [OPTION]... [TEMPLATE] 
...
-u, --dry-run
    do not create anything; merely print a name
... 
--tmpdir[=DIR]
    interpret TEMPLATE relative to DIR. If DIR is not specified, 
use $TMPDIR if set, else /tmp. With this option, TEMPLATE must 
not be an absolute name. Unlike with -t, TEMPLATE may contain 
slashes, but mktemp creates only the final component. 

Therefore, either of the following are equivalent and should work:

dirname $(mktemp -u --tmpdir)

or

echo ${TMPDIR:-/tmp}

It's possible to imagine that the former might work while the latter doesn't on systems where either TMPDIR or /tmp are not used, but that have implemented the mktemp spec, albeit with a different explanation under the --tmpdir[=DIR] option. (However I am presently unable to test.)

0

I recommend a more comprehensive approach by checking all the possible env's that could be set. Also, let's not forget the XDG Base Directory specification by checking the XDG_RUNTIME_DIR.

https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html

echo ${XDG_RUNTIME_DIR:-${TMPDIR:-${TMP:-${TEMP:-/tmp}}}}

This will most likely return /run/user/1000 for a system following XDG Base Directory, and if not, will check TMPDIR, TMP, and TEMP in order. If nothing is set, then it will return /tmp.

  • 2
    Reading that specification, it seems that $XDG_RUNTIME_DIR is mainly for small files such as PID files, sockets, etc. It explicitly says that it is not to be used for "large files", which is what the temporary directory is often used for. It also says that if the $XDG_RUNTIME_DIR can not be used, a message should be printed to warn the user of this fact before selecting another directory. That is if you want to follow that standard. – Kusalananda Jan 11 '22 at 10:10