Files and data
Create and clean temporary files
Use mktemp and a trap so unique temporary data is removed on success, failure, or interruption.
Scripts need scratch space: an archive to assemble, a download to inspect, a sorted copy of a log. Hardcoding a path like /tmp/work.txt looks harmless, but predictable temporary filenames can collide or be replaced by another user on a shared machine. mktemp asks the operating system for a unique private path instead.
Create a temporary directory with cleanup
work=$(mktemp -d)
cleanup() { rm -rf -- "$work"; }
trap cleanup EXIT INT TERM
printf 'working in %s\n' "$work"
# working in /tmp/tmp.X8s2Lk4bQz
mktemp -d creates a directory only your user can access and prints its path, which we capture with command substitution.
The trap line makes this reliable. A trap registers a command to run when the shell receives a signal or, with the special EXIT condition, whenever the script ends. This one runs cleanup on normal exit, on Ctrl-C (INT), and on termination (TERM). The directory disappears whether the script succeeds, fails, or gets interrupted halfway.
The -- in rm -rf -- "$work" ends option parsing, so even a path starting with a dash cannot be misread as a flag.
Verify the cleanup runs
Exit normally and interrupt the script. Confirm the exact generated directory is removed both times:
./make-report
# working in /tmp/tmp.QpB7wq2c1M
ls /tmp/tmp.QpB7wq2c1M
# ls: cannot access '/tmp/tmp.QpB7wq2c1M': No such file or directory
Run it again and press Ctrl-C mid-run, then check again. If the directory survives an interrupt, the trap was registered too late. Register it immediately after creating the resource, before any work that can fail.
The failure mode to fear
rm -rf next to a variable that might be empty is the classic shell disaster:
rm -rf "$workdir/cache" # if $workdir is empty: rm -rf /cache
Validate the variable before any recursive deletion. set -u catches unset names, and a one-line guard costs nothing:
[[ -n $work ]] || exit 1
Never build a destructive target from an empty or broad environment variable. The pattern above (mktemp output, straight into a trap) is safe precisely because the value comes from a program you just ran, not from inherited environment.
Lesson completed