opscape

Files and directories

mktemp

Create a temporary file or directory with a unique, unpredictable name and print that name.

mktemp [OPTION...] [TEMPLATE]

8 of 8 examples run in Debian 13.7 on 2026-10-31 · coreutils 9.7-3 · manual: mktemp(1)

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"
output
/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"
output
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

job.sh
#!/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
output
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
output
/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
output
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"
outputexit 2
/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
output
"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
explain
outputexit 1
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 of 600.

  • Forgetting cleanup leaves files behind on every run, including failed ones. Put the trap ... EXIT right after the mktemp.

  • Files from mktemp are mode 600; if you mv one into place as a config file that others must read, chmod it 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, -t takes a prefix rather than a template, and the default name format differs. A full template such as mktemp /tmp/foo.XXXXXX (X's at the end) behaves the same on both.

  • --suffix and -p are GNU options.

Options worth knowing

A selection, described in our own words. For the full list, see mktemp(1) or mktemp --help.

OptionWhat it does
-d, --directoryCreate a directory instead of a file.
-u, --dry-runOnly print a name; create nothing (unsafe).
-q, --quietDo not print an error if creation fails.
-p DIRCreate the file in DIR instead of $TMPDIR or /tmp.
--tmpdir[=DIR]Like -p; without DIR, use $TMPDIR or /tmp.
-tInterpret the template relative to $TMPDIR or /tmp.
--suffix SUFFAppend SUFF to the template; the X's must come before it.

Related