Shell Scripts: Don’t Let Your Temp Files Become a Mess (or a Danger)
By Saket Jain Published Linux/Unix
Shell Scripts: Don’t Let Your Temp Files Become a Mess (or a Danger)
Technical Briefing | 9/18/2026
Every sysadmin has written a script that needs a temporary place to stash files. Maybe it’s a download, a working copy, or some intermediate processing output. You toss it in /tmp, probably give it a unique name with a timestamp or the PID, and then mostly forget about it. That’s fine, it works, until it doesn’t. And when it doesn’t, it can leave behind gigabytes of garbage, or worse, wipe out something critical because your cleanup logic had a bad day.
The Safe Bet: mktemp Does the Heavy Lifting
Look, rolling your own temporary file generation is almost always a bad idea. Seriously. You might think `my-script-$$` or `$(date +%s)` is enough, but it opens you up to race conditions and predictable names. What you want is something truly unique, something that won’t conflict with another instance of your script or another process. That’s where `mktemp` comes in. It’s built for exactly this. It creates a temporary file or directory and gives you back the path, atomically, ensuring uniqueness and preventing those nasty race conditions that can silently fail or create security holes. It’s been in GNU coreutils for ages, and there’s no excuse not to use it.
#!/usr/bin/env bash
set -euo pipefail
# Create a unique temporary directory
# -d for directory, -t for template prefix, XXXXXX ensures uniqueness
TEMP_DIR=$(mktemp -d -t myapp.XXXXXX)
# Define a cleanup function
function cleanup {
if [[ -d "${TEMP_DIR}" ]]; then
echo "Cleaning up temporary directory: ${TEMP_DIR}" >&2
rm -rf "${TEMP_DIR}"
else
echo "Temporary directory ${TEMP_DIR} not found, skipping cleanup." >&2
fi
}
# Register the cleanup function to run on script exit, interrupt, or termination
trap cleanup EXIT INT TERM
echo "Working in temporary directory: ${TEMP_DIR}"
# --- Simulate some work ---
# Create a file inside our temp dir
echo "This is some temporary data specific to this run." > "${TEMP_DIR}/data.txt"
# Copy some system info into another temp file
cp /etc/os-release "${TEMP_DIR}/os-info.txt"
# Show contents (optional, for demonstration)
ls -l "${TEMP_DIR}"
cat "${TEMP_DIR}/data.txt"
sleep 3 # Simulate some longer operation
echo "Script finished its work." # Cleanup will run automatically here
Where Temp File Logic Usually Bites You
- Forgetting to `trap` for cleanup: Your script finishes, but the temporary directory (and its contents) sticks around. Repeat this a few times, and you’ve got a problem.
- Rolling your own random names: `mktemp` isn’t just about randomness; it’s about atomic creation. A collision could overwrite someone else’s files, or expose your data.
- Not quoting your variables: This is the real killer. An unquoted `$TEMP_DIR` in an `rm -rf` command can expand to `rm -rf /` if `TEMP_DIR` is empty or somehow evaluates to nothing. I’ve seen this happen in production, and it’s not pretty. Always quote your variables, especially in `rm` commands.
- Assuming `/tmp` will get automatically cleaned up: Some systems do, some don’t, some only on reboot. Don’t rely on it. Manage your own mess.
The `trap` is non-negotiable for any script creating temporary files. You absolutely need to guarantee that cleanup function runs, even if your script errors out, gets killed with Ctrl+C, or receives a `TERM` signal from process management like `systemd`. And that check `if [[ -d “${TEMP_DIR}” ]];` inside the `cleanup` function? It’s defensive programming. What if `mktemp` failed in the first place, or another process deleted the directory out from under you? Better to check than to run `rm -rf` on an empty or invalid path. And for the love of all that is holy, always, always, *always* quote your variables when passing them to `rm -rf`. An empty variable combined with `rm -rf` is how you nuke your root filesystem in a worst-case scenario. That’s not a theoretical problem; that’s a call at 3 AM.
Treat temporary files for what they are: ephemeral, short-lived, and disposable. Your scripts should be self-contained and responsible for their own transient mess. Embrace `mktemp` and solid `trap` logic, and you’ll save yourself a lot of headaches, disk space, and potentially catastrophic data loss. It’s a small change with a massive impact on the robustness of your automation.
