Files and directories
mktemp
Create a temporary file or directory with a unique, unpredictable name and print that name.
mktemp [OPTION...] [TEMPLATE]
Scripts that need scratch space should never use a fixed name like /tmp/output.txt: two runs
at once would overwrite each other, and on a shared machine another user could create that
name first as a symlink to something of yours. mktemp creates the file atomically with a
random name, mode 600 (owner only), and prints the name so you can capture it.
The pattern every script should know is: create with mktemp, store the name in a variable, and
delete it in an EXIT trap so it is cleaned up however the script ends. mktemp -d does the same
for a directory, which is handy when you need several files.
Files go in $TMPDIR if set, otherwise /tmp. A template controls the name: its run of Xs
(at least three) is replaced with random characters. Without one, the name is tmp. plus ten
random characters.
Examples
Create a temporary file
f=$(mktemp)
echo "$f"
ls -l "$f"
/tmp/tmp.HF7YSqL4Lb -rw------- 1 dev dev 0 Oct 31 20:20 /tmp/tmp.HF7YSqL4Lb
The name is random (tmp. plus ten characters) and differs on every run. The file exists,
is empty and is readable only by its owner.
Create a temporary directory
d=$(mktemp -d)
ls -ld "$d"
drwx------ 2 dev dev 2 Oct 31 20:20 /tmp/tmp.gORisNblxV
-d creates a directory with mode 700, a private workspace for several files.
Clean up automatically when the script exits
#!/bin/bash
set -euo pipefail
work=$(mktemp -d)
trap 'rm -rf -- "$work"' EXIT
sort data/fruits.txt | uniq -c > "$work/counts"
echo "working in $work"
head -3 "$work/counts"
bash job.sh
ls /tmp
working in /tmp/tmp.mw6TXfuzy9
3 apple
2 banana
2 cherry The EXIT trap runs when the script ends for any reason, including an error under
set -e, so the directory is removed. The final ls shows /tmp empty again.
Choose a recognizable name
mktemp /tmp/backup-XXXXXX.log
mktemp --suffix=.csv /tmp/export-XXXXXXXX
/tmp/backup-4zjz15.log /tmp/export-TXIOIVEn.csv
The run of Xs is replaced with random characters. When text follows the Xs, GNU
mktemp keeps it as a suffix; --suffix says so explicitly. A recognizable prefix tells
you which program left a file behind.
Create the file in a specific directory
mkdir scratch
mktemp -p scratch
TMPDIR=$PWD/scratch mktemp -t report.XXXX
scratch/tmp.tmdINgeKHj /home/dev/demo/scratch/report.6yKB
-p DIR puts the file in DIR. With -t, the template is placed in $TMPDIR, which is
how you let users point temporary files at a bigger disk.
Generate a name without creating anything
name=$(mktemp -u)
echo "$name"
ls "$name"
/tmp/tmp.X07fxWaKjK ls: cannot access '/tmp/tmp.X07fxWaKjK': No such file or directory
-u only prints a name. Nothing is created, as the failing ls shows, so another process
could take that name before you do: avoid -u except for things like named pipes that you
create right away.
Replace a file atomically
tmp=$(mktemp data/config.json.XXXXXX)
jq '.version = "2.5.0"' data/config.json > "$tmp" && mv "$tmp" data/config.json
jq .version data/config.json
"2.5.0"
Writing to a temporary file in the same directory and then renaming it with mv means
readers see either the old file or the new one, never a half-written one. Note that the new
file keeps mktemp's 600 mode.
Too few X's in the template
mktemp /tmp/run-XX
mktemp: too few X's in template ‘/tmp/run-XX’
The template needs at least three Xs to give enough randomness; GNU mktemp refuses
shorter ones.
Common pitfalls
touch /tmp/myscript.$$is not a safe substitute: process IDs are predictable, and the file is created with your normal umask instead of600.Forgetting cleanup leaves files behind on every run, including failed ones. Put the
trap ... EXITright after themktemp.Files from
mktempare mode600; if youmvone into place as a config file that others must read,chmodit first.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
On BSD/macOS,
-ttakes a prefix rather than a template, and the default name format differs. A full template such asmktemp /tmp/foo.XXXXXX(X's at the end) behaves the same on both.--suffixand-pare GNU options.
Options worth knowing
A selection, described in our own words. For the full list, see mktemp(1) or mktemp --help.
| Option | What it does |
|---|---|
-d, --directory | Create a directory instead of a file. |
-u, --dry-run | Only print a name; create nothing (unsafe). |
-q, --quiet | Do not print an error if creation fails. |
-p DIR | Create the file in DIR instead of $TMPDIR or /tmp. |
--tmpdir[=DIR] | Like -p; without DIR, use $TMPDIR or /tmp. |
-t | Interpret the template relative to $TMPDIR or /tmp. |
--suffix SUFF | Append SUFF to the template; the X's must come before it. |
Related
mkdirCreate directories, optionally with all missing parents.touchUpdate a file's timestamps, creating it empty if it does not exist.rmDelete files, and with -r whole directory trees. There is no undo.trapRun a command when the shell receives a signal or exits, typically to clean up temporary files.- Traps and signalsRunning cleanup code with trap on EXIT, handling INT and TERM, the ERR pseudo-signal, and the timing and scoping rules that trip people up.
- Strict mode and its caveatsWhat set -euo pipefail actually does, the cases where -e silently does nothing, the traps in -u and pipefail, and a balanced way to use it.