Temporary directories created by a Zsh script can remain on disk when a command fails or the operator interrupts the run. A cleanup trap gives the script a final handler that removes temporary state before the shell process exits.
The trap builtin registers code for shell events such as EXIT. Pairing mktemp -d with a cleanup function keeps the workspace unique and limits removal to the directory that the script created.
The sample writes the temporary directory path to cleanup.path so the parent shell can verify removal after Zsh exits. It saves the original exit code before removing files, then returns that code so cleanup does not hide a failed command. Treat the cleanup's rm -rf as sensitive by guarding the variable, quoting the path, and using -- before the directory name. A trap cannot run after KILL, power loss, or a hard process crash, so temporary data still needs a separate recovery path when it must be kept.
Related: How to debug a Zsh script
Related: How to use conditionals in Zsh
Related: Clean up temporary files in Bash with trap
#!/usr/bin/env zsh
emulate -L zsh
setopt err_exit no_unset pipe_fail
path_file=${1:-cleanup.path}
mode=${2:-ok}
workdir=
cleanup() {
local exit_status=$?
if [ -n "${workdir:-}" ] && [ -d "$workdir" ]; then
rm -rf -- "$workdir"
print -r -- "removed $workdir"
fi
return $exit_status
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
workdir=$(mktemp -d)
print -r -- "$workdir" > "$path_file"
print -r -- "created $workdir"
print -r -- "report data" > "$workdir/report.txt"
if [ "$mode" = fail ]; then
print -u2 -- "simulated failure"
exit 1
fi
print -r -- "finished work"
The cleanup function uses rm -rf. Keep $workdir quoted, guarded, and assigned only from mktemp -d so the script does not remove an unintended path.
Zsh uses status as a special parameter, so the cleanup function saves the code in exit_status. The INT and TERM traps exit with signal-style status codes, then the EXIT trap runs cleanup once.
$ zsh -n temp-cleanup.zsh
No output from zsh -n means Zsh parsed the file without finding a syntax error.
$ zsh temp-cleanup.zsh cleanup.path created /tmp/tmp.467voMLHRt finished work removed /tmp/tmp.467voMLHRt
$ cleanup_dir=$(cat cleanup.path)
$ test ! -d "$cleanup_dir" && printf 'removed\n' removed
$ zsh temp-cleanup.zsh cleanup.path fail created /tmp/tmp.BAWcdhSlDC simulated failure removed /tmp/tmp.BAWcdhSlDC
The command exits with status 1 after printing simulated failure, but the cleanup function returns the saved status after removing the temporary directory.
$ cleanup_dir=$(cat cleanup.path)
$ test ! -d "$cleanup_dir" && printf 'removed after failure\n' removed after failure
$ rm -f cleanup.path temp-cleanup.zsh