shell 脚本需要做的最常见的事情之一是创建和操作临时文件。这样做安全是一种痛苦,因为你需要避免名称冲突,避免竞争条件,确保该文件具有正确的权限,等等(参见GNU Coreutils的手册和琐碎的博客文章这方面的迹象对这些更详细的讨论问题。)大多数类 Unix 操作系统通过提供mktemp
处理所有这些问题的命令来解决这个问题。但是,这些mktemp
命令的语法和语义没有标准化。如果您真的想安全且可移植地创建临时文件,则必须求助于丑陋的杂物,例如以下内容:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
Run Code Online (Sandbox Code Playgroud)
(此变通方法利用了宏处理器m4
是 POSIX 的一部分这一事实,并m4
公开了mkstemp()
同样由 POSIX 定义的 C 标准库函数。)
鉴于这一切,为什么 POSIX 没有标准化一个mktemp
命令,保证它的存在和至少它行为的某些方面?这是 POSIX 委员会的一个明显疏忽,还是委员会mktemp
实际上已经讨论了标准化的想法并因某些技术或其他原因被拒绝?
我之前已经注意到这一点,但在我回答“如何将目录移动到同名目录中? ”时它又被提出来了:
的mktemp
在MacOS实用程序不表现一样在Linux或BSD(或至少OpenBSD的)的同名的相对于所述公用事业TMPDIR
环境变量。
在当前目录下创建一个临时文件,我通常可以说
tmdfile=$(TMPDIR=. mktemp)
Run Code Online (Sandbox Code Playgroud)
或者
tmpfile=$(TMPDIR=$PWD mktemp)
Run Code Online (Sandbox Code Playgroud)
(对于带有 的临时目录也类似mktemp -d
)。
在 macOS 上,我必须通过给它一个实际模板来强制该实用程序使用当前目录,如
tmpfile=(mktemp ./tmp.XXXXXXXX)
Run Code Online (Sandbox Code Playgroud)
因为使用更方便的tmpfile=$(TMPDIR=. mktemp)
将忽略该TMPDIR
变量并/var/folders/qg/s5jp5ffx2p1fxv0hy2l_p3hm0000gn/T
在类似命名的目录下或中创建文件。
mktemp
macOS 上的手册提到
如果
-t prefix
给出该选项,mktemp
将根据前缀和_CS_DARWIN_USER_TEMP_DIR
配置变量(如果可用)生成模板字符串。如果_CS_DARWIN_USER_TEMP_DIR
不可用,回退位置 是TMPDIR
和/tmp
。
在我的系统上,_CS_DARWIN_USER_TEMP_DIR
似乎未设置:
$ getconf _CS_DARWIN_USER_TEMP_DIR
getconf: no such configuration parameter `_CS_DARWIN_USER_TEMP_DIR'
Run Code Online (Sandbox Code Playgroud)
但是例如
tmpfile=$(TMPDIR=. mktemp -t hello)
Run Code Online (Sandbox Code Playgroud)
仍然在下创建一个文件/var/folders/.../
(也在使用$PWD
代替 时.
)。
我注意到
$ getconf …
Run Code Online (Sandbox Code Playgroud) 我经常直接想要一个临时文件,我可以在其中解压缩一些存档(或创建一个临时项目),查看一些文件。预先无法预测特定目录可能需要多长时间。
此类目录通常是杂乱的主目录/tmp
、项目目录。他们通常有一些弱密码之类的名字,比如qqq
, 1
,test
在一个月后变得不具描述性。
是否有一些 shell 命令或外部程序可以帮助管理此类丢弃目录,以便在我对它们失去兴趣时自动清理它们,我不需要为它们命名,但可以给出一个名字并容易持久化?
如果没有这样的工具,创建一个是个好主意吗?
我试图理解斯蒂芬基特对这个问题的回答,他用以下代码创建了一个临时目录:
#!/bin/bash
scripttmp=$(mktemp -d) # Create a temporary directory (these will usually be created under /tmp or /var/tmp/)
Run Code Online (Sandbox Code Playgroud)
每次我运行这个命令时,我都会看到一个新的临时目录/tmp/
(我不知道它会出现在那里,直到在这里阅读 Roaima 的回答):
IIUC,常规目录和临时目录之间没有编程上的区别(唯一的区别在于如何使用这些目录,即每个目录在机器上停留的时间)。
如果没有程序上的差异,为什么要优先mktemp -d
于更小mkdir
?
我最近阅读了--help
文本mktemp
(man
页面不可用)并发现了这个:
-u, --dry-run do not create anything; merely print a name (unsafe)
Run Code Online (Sandbox Code Playgroud)
为什么这是“不安全”?是否有任何具体原因将其标记为这样?
以前 mktemp 用于在/tmp
. 今天我注意到 mktemp 正在创建文件而 $PWD
不是在/tmp
?
笔记:
我能够做到:ls /tmp
$ mktemp --version
mktemp (GNU coreutils) 8.30
Run Code Online (Sandbox Code Playgroud)
$ echo $TMPDIR
$
Run Code Online (Sandbox Code Playgroud) mktemp ×6
files ×2
gnu ×2
bash ×1
coreutils ×1
directory ×1
filenames ×1
filesystems ×1
interactive ×1
macos ×1
mkdir ×1
posix ×1
shell-script ×1
tmp ×1