Home / Alt manpages / mktemp(1)

  • mktemp(1)
  • User command
  • linux

mktemp on Linux: Safe Temporary Files and Directories

By the end of this guide you will be able to create a uniquely named temporary file or directory, use its printed pathname in a shell script, and remove it when the work is finished. The examples use GNU coreutils 9.4, installed locally on this system.

Prerequisites: a shell account and permission to write to the chosen temporary directory. Allow about 10 minutes for the examples. No elevated privileges are needed. Do not run these tests as root unless the surrounding task genuinely requires it.

Checkpoint 1: create a temporary file

Run mktemp with a template ending in at least three consecutive X characters. Each X is replaced while the file is created, and the resulting pathname is printed.

temp_file=$(mktemp /tmp/report.XXXXXX)
printf 'temporary data\n' > "$temp_file"
printf 'Created: %s\n' "$temp_file"
cat "$temp_file"

Typical output looks like this, although the random suffix will differ:

Created: /tmp/report.K8q3Lm
temporary data

The command creates a regular file with user read and write permission, reduced by the process umask. The pathname is not a promise that a file will exist forever, so keep it in a variable and quote it whenever you use it. Quoting also protects names containing characters that the shell could otherwise interpret.

Verify both the type and permissions before continuing:

test -f "$temp_file" && stat -c '%A %n' "$temp_file"

You should see a regular file owned by your account, normally with permissions equivalent to -rw------- when the umask is restrictive. Exact permissions depend on the umask, so do not build a security decision around one displayed mode.

Checkpoint 2: create a temporary directory

Pass --directory when the temporary object should contain several files. The final directory component still needs three or more X characters.

temp_dir=$(mktemp --directory /tmp/report-work.XXXXXX)
printf 'intermediate result\n' > "$temp_dir/result.txt"
printf 'Working directory: %s\n' "$temp_dir"
find "$temp_dir" -maxdepth 1 -type f -printf '%f\n'

Expected output is:

Working directory: /tmp/report-work.A1b2C3
result.txt

The directory is created with user read, write and search permission, again subject to the umask. Because mktemp creates the directory before returning, two processes can safely receive different names even when they use the same template.

Checkpoint 3: control the location

With --tmpdir, the template is interpreted relative to a directory. If no directory is supplied, GNU mktemp uses $TMPDIR when it is set, otherwise /tmp. This is useful when a job has a dedicated scratch area.

scratch=$(mktemp --directory /tmp/mktemp-demo.XXXXXX)
temp_file=$(mktemp --tmpdir="$scratch" input.XXXXXX)
printf 'data in the selected directory\n' > "$temp_file"
case "$temp_file" in
  "$scratch"/*) echo "Placed in scratch: $temp_file" ;;
  *) echo 'Unexpected location' >&2; exit 1 ;;
esac

Unlike the older -t option, --tmpdir can use a template containing path separators, but it creates only the final component. The template must not be an absolute pathname when this option is used. The short -t form is deprecated and treats the template as a single filename component, so prefer --tmpdir in new scripts.

Checkpoint 4: clean up deliberately

Temporary objects are not automatically removed when the shell exits. Remove the file after use, and remove a directory only after checking that it is the directory you created. This is a destructive step: a mistaken pathname can delete unrelated data.

rm -- "$temp_file"
rm -- "$temp_dir/result.txt"
rmdir -- "$temp_dir"

test ! -e "$temp_file" && test ! -e "$temp_dir"
echo 'Temporary objects removed'

rmdir refuses to remove a non-empty directory, which is a useful guard. If the directory contains more files and you have confirmed its pathname, remove those known files first. Avoid turning a temporary-directory cleanup into an unreviewed recursive deletion.

For scripts that can be interrupted, install a cleanup trap immediately after creation:

temp_dir=$(mktemp --directory /tmp/report-work.XXXXXX)
trap 'rm -rf -- "$temp_dir"' EXIT HUP INT TERM

# Use "$temp_dir" here.
printf 'ready\n'

This trap is convenient, but rm -rf is irreversible. Keep the variable private to the script, initialise it from mktemp, and never replace it with an unchecked user-supplied path. If cleanup itself needs stronger safeguards, remove known children and use rmdir instead.

Common traps and failure modes

  • Using --dry-run for real work: -u only prints a possible name and creates nothing. The manual marks it unsafe because another process can claim that name before you use it. Do not use it to reserve a pathname.
  • Too few X characters: a template must contain at least three consecutive X characters in its last component. A failed creation prints a diagnostic and returns a non-zero status.
  • Ignoring the exit status: capture the pathname only after confirming success. In a script, use temp_file=$(mktemp ...) with shell error handling appropriate to the rest of the script.
  • Assuming /tmp is always right: use --tmpdir or a deliberate $TMPDIR when data belongs on a different filesystem or needs a controlled capacity limit.
  • Using a predictable hand-built name: do not create /tmp/report.txt yourself. mktemp combines name generation and creation, closing the race in which an attacker or another process creates the name first.

Done means

  • A temporary file was created with a template containing six or more X characters.
  • A temporary directory was created with --directory when a workspace was needed.
  • The printed pathname was stored, quoted, and checked before use.
  • --dry-run and deprecated -t were not used for new work.
  • Known temporary files were removed, and the directory was removed only after it was empty.