Bash:临时文件别随手写死,`mktemp` 更稳一点

37 次浏览3 条回复

写小脚本时有时要落一个中间文件,如果直接写 /tmp/demo.txt,多开几个终端或者脚本重复跑就容易互相覆盖。mktemp 可以帮忙生成一个不容易撞名的临时文件。

环境:bash 4+,Linux/macOS 常见环境可以试:

tmp=$(mktemp)
printf 'hello temp\n' > "$tmp"
cat "$tmp"
rm "$tmp"

输出会看到:

hello temp

如果想要临时目录,也可以用:

dir=$(mktemp -d)
printf 'cache\n' > "$dir/data.txt"
cat "$dir/data.txt"
rm -r "$dir"

我觉得它适合那种一次性转换、下载后处理的小脚本。记得变量加引号,最后清理掉就行。

这里再补一句:如果脚本中间可能报错,清理可以挂到 trap 上,不然临时文件偶尔会留在 /tmp 里。

tmp=$(mktemp)
trap 'rm -f "$tmp"' EXIT

printf 'hello temp\n' > "$tmp"
cat "$tmp"

小脚本这样写会省心一点。

HosuLv1#1

这里再补一句:如果脚本中间可能报错,清理可以挂到 trap 上,不然临时文件偶尔会留在 /tmp 里。

tmp=$(mktemp)
trap 'rm -f "$tmp"' EXIT

printf 'hello temp\n' > "$tmp"
cat "$tmp"

小脚本这样写会省心一点。

临时目录那段我还挺常用的,多个中间文件放一起会清楚点。一般会写成这样:

dir=$(mktemp -d)
trap 'rm -rf "$dir"' EXIT

printf 'cache\n' > "$dir/data.txt"
printf 'result\n' > "$dir/out.txt"
cat "$dir/out.txt"

小心点就是 rm -rf 只对 mktemp -d 成功后的变量用,变量也一定加引号。不然清理临时目录这件事反而容易变吓人。

还有个小细节:想保留后缀的话可以给 mktemp 一个模板,不然有些工具会靠扩展名判断格式。

tmp=$(mktemp --suffix=.json)
printf '{"ok":true}
' > "$tmp"
cat "$tmp"
rm -f "$tmp"

GNU coreutils 里这个挺方便;macOS 上参数不太一样,脚本要跨平台的话最好先确认一下 mktemp --helpman mktemp