16

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?

Perostek Balveda
  • 261
  • 1
  • 2
  • 3
  • 1
    On POSIX compliant system, using `/tmp` should be ok. See http://unix.stackexchange.com/a/146738/38906 – cuonglm Mar 17 '17 at 13:29
  • 2
    Never heard of `$TMP`/`$TEMP` to mean an area for temporary files. You may be confusing with [Microsoft operating systems](https://blogs.msdn.microsoft.com/oldnewthing/20150417-00/?p=44213). – Stéphane Chazelas Mar 17 '17 at 13:39
  • 2
    Does this answer your question? [Finding the correct tmp dir on multiple platforms](https://unix.stackexchange.com/questions/174817/finding-the-correct-tmp-dir-on-multiple-platforms) – Jakub Kukul May 05 '21 at 09:00

3 Answers3

28

$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
  • 209
  • 2
  • 9
Kusalananda
  • 320,670
  • 36
  • 633
  • 936
  • 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](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html#tag_17_04). – 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
2

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.)

Craig Hicks
  • 644
  • 8
  • 13
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.

Vlastimil Burián
  • 27,586
  • 56
  • 179
  • 309
Clay Risser
  • 109
  • 1
  • 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