The mktemp command in Linux creates temporary files and directories with unique, unpredictable names, which is the safest way to handle scratch data inside shell scripts and system tasks.
Most shell scripts you will read online create temporary files with something like /tmp/mydata.txt or /tmp/backup-$$.log, which works until two copies of the script run at the same time, or until a malicious user guesses the filename and drops a symlink in /tmp pointing to /etc/passwd. Suddenly, your harmless script is overwriting system files, and you have a real problem on your hands.
The fix is mktemp, a small utility that creates a guaranteed-unique file or directory with safe permissions and hands you back the path. Every serious sysadmin script uses it, and once you see how it works you will never go back to hand-rolled temp filenames again.
Why Sysadmins Rely on mktemp
The /tmp directory is shared by every user on the system, which means any script writing there has to assume other processes are reading and writing at the same time.
If two people run the same backup script and both try to create /tmp/backup.log, one will quietly overwrite the other. Race conditions like this are one of the oldest sources of bugs in Unix scripting.
mktemp solves two problems at once. First, it guarantees the filename is unique by appending random characters, so parallel runs never collide. Second, it creates the file atomically with permissions set to 600, meaning only the owner can read or write it, which blocks a whole category of symlink attacks.
You will find mktemp preinstalled on every modern Linux distribution because it ships as part of the GNU coreutils package. There is nothing to install, and the command works the same on Ubuntu, Debian, RHEL, Rocky Linux, and Fedora.
Basic mktemp Syntax Explained
The simplest form of the command takes no arguments at all. You just type mktemp and it prints the path of the new file it just created for you. The file already exists on disk before the command returns, which is what makes the operation safe.
mktemp
Output:
/tmp/tmp.kJ9mN2xQ8F
The random suffix kJ9mN2xQ8F is different every time you run the command, which is how uniqueness is guaranteed. You can now redirect script output into that path with confidence that nothing else on the system is touching it. The permissions on the new file are automatically set to read-write for your user only.
Common Beginner Mistakes
New users often run mktemp and then forget to capture the returned path, which means they lose track of the file they just created. Always assign the output to a variable like TMPFILE=$(mktemp) so your script can reference it later.
1. Create a Temporary File Inside a Script
The standard pattern in production scripts is to capture the path into a variable and set up a cleanup trap so the file is removed when the script exits, even if it crashes. This three-line pattern is the single most useful thing to memorize about mktemp.
TMPFILE=$(mktemp) trap "rm -f $TMPFILE" EXIT echo "some data" > $TMPFILE cat $TMPFILE
Output:
some data
The trap line tells the shell to run rm -f $TMPFILE whenever the script exits for any reason, so you never leave orphaned files cluttering /tmp.
Even if your script dies partway through because of an error, the trap still fires and cleans up. That is what makes this pattern safe for long-running production scripts.
Common Beginner Mistake: Forgetting the trap line is the number one mistake, and over weeks your /tmp fills with abandoned files. Always pair mktemp with a cleanup trap in the very next line.
Common Beginner Mistakes
Forgetting the trap line is the number one mistake, and over weeks your /tmp fills with abandoned files. Always pair mktemp with a cleanup trap in the very next line.
2. Create a Temporary Directory with -d
When your script needs to work with multiple files, for example extracting a tarball or staging a build, you want a whole directory rather than a single file. The -d flag handles this case and returns the path to a freshly created private directory.
TMPDIR=$(mktemp -d) echo $TMPDIR ls -ld $TMPDIR
Output:
/tmp/tmp.8vX2mNqL4K drwx------ 2 ravi ravi 4096 Apr 20 10:42 /tmp/tmp.8vX2mNqL4K
The permissions drwx------ mean only your user can enter or list the directory, which is exactly what you want for private scratch space. Clean it up with rm -rf $TMPDIR in your trap instead of plain rm -f, otherwise the removal fails because rm without -r refuses to delete directories.
Common Beginner Mistakes
Using rm -f on a directory fails silently and leaves the directory behind. Always use rm -rf when cleaning up a directory created with mktemp -d.
3. Use a Custom Template for Readable Names
When you are debugging and need to spot your script’s temp files in /tmp, a custom template makes them easy to find. The template must end with at least three X characters, which mktemp replaces with random data to keep uniqueness guaranteed.
mktemp backup-log-XXXXXX
Output:
backup-log-a8K2mQ
Notice the file was created in the current directory, not /tmp, because the template did not include a full path. This catches a lot of people by surprise the first time. To force the file into /tmp regardless of where the script runs, combine the template with the -t flag shown in the next example.
Common Beginner Mistakes
Using fewer than three X characters throws an error like mktemp: too few X's in template, so stick with six X characters as the safe default.
4. Force Files Into /tmp with -t
The -t flag tells mktemp to place the file inside the directory named by the TMPDIR environment variable, falling back to /tmp if that variable is not set. This is the pattern to use in scripts you plan to distribute.
mktemp -t backup-XXXXXX.log
Output:
/tmp/backup-a8K2mQ.log
Your script now respects the user’s TMPDIR setting, which matters on systems where /tmp is small or where admins have moved temp storage to a larger disk. The script works correctly everywhere without changes. That portability is why -t shows up in most open-source shell tooling.
Common Beginner Mistakes
Hardcoding /tmp/ in the template defeats the point of -t. Let mktemp pick the directory so your script honors system configuration.
5. Do a Dry Run with –dry-run
Sometimes you just want the name without actually creating the file, for example when generating a path to pass to another command that will create the file itself. The --dry-run flag returns a safe unique name without touching the filesystem at all.
mktemp --dry-run -t staging-XXXXXX
Output:
/tmp/staging-pL9mK3
The file /tmp/staging-pL9mK3 does not exist yet, so a subsequent command that expects the file to already be there will fail. Use --dry-run only when the next command in your pipeline will create the path itself, like tar extracting into a directory or ssh-keygen writing a new key file.
Common Beginner Mistake
Treating --dry-run output as a real file path and writing to it without creating the file first gives a No such file or directory error. Either skip –-dry-run or follow it with touch or mkdir.
Most Useful mktemp Flags
A handful of flags cover almost every real script you will write with mktemp command. You rarely need more than these five in day-to-day work.
-d– creates a directory instead of a file.-t– places the file inside$TMPDIRor/tmp.-p DIR– places the file inside a directory you specify.-uor--dry-run– returns a name without creating anything.-q– suppresses error messages, useful when you handle errors yourself.
The -p flag is worth knowing about because it lets you pick any directory you control, for example mktemp -p /var/cache/myapp. This is handy when /tmp is mounted with noexec and you need to write a script there, or when you want temp data to live on a specific disk with more space.
Conclusion
You now know why hand-rolled temp filenames are a bad idea, how mktemp fixes the problem with atomic creation and safe permissions, and the five patterns that cover almost every script you will ever write.
The combination of mktemp plus a trap cleanup line is the single most useful habit you can pick up for writing reliable Bash scripts, and it will save you from a class of bugs that are painful to track down in production.
Open a terminal right now and try the three-line pattern from example, copy:
TMPFILE=$(mktemp); trap "rm -f $TMPFILE" EXIT; echo test > $TMPFILE; cat $TMPFILE
into a script, run it, and then run ls /tmp to confirm the file is gone after the script exits. That one exercise teaches more than reading ten man pages on the subject.
Have you been bitten by a race condition or a symlink attack because of unsafe temp file handling? What pattern do you use in your own scripts? Tell us in the comments below.





