在OS X中修复或替代mktemp


72

我正在查看其他人使用的bash脚本mktemp

TEMP=`mktemp --directory`

但是,此行在我的机器(OS X 10.6)上不起作用。

我将如何修复此行,使其与跨un * x平台兼容?编辑:替代命令也将足够。

Answers:


108

以下是我最终用来可靠地创建一个在Linux和Darwin(Mac OS X 10.11之前的所有版本)上均可使用的临时目录的信息,而无需进行硬编码$TMPDIR/tmp

mytmpdir=`mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir'`

背景:

GNU mktemp命令不需要任何参数。Plain mktemp将起作用,并在系统的临时目录中创建一个临时文件。

Plain mktemp -d将创建目录而不是文件,而这正是您要在Linux上使用的目录。

(gnu-coreutils)$ man mktemp
> ..
> If DIR is not specified, uses $TMPDIR if set, else /tmp.
> ..

默认情况下,GNU mktemp使用模板tmp.XXXXXXXXXX作为子目录(或文件)的名称。要自定义此模板,-t可以使用该选项。

OSX的mktemp没有默认模板,需要指定模板。不幸的是,在GNU mktemp将模板作为-t选项的情况下,在OSX上将其作为位置参数传递。相反,OSX的mktemp具有一个-t表示其他含义的选项。-tOSX上的选项记录为模板的“前缀”。它被扩展为{prefix}.XXXXXXXX,因此它会自动向其中添加X(例如mktemp -d -t example可以example.zEJZWCTQ在temp目录中创建)。

我惊讶地发现,在许多Linux环境,$TMPDIR不是默认设置。设置后,许多CLI程序都支持它,但仍需要使用默认值/tmp。这意味着传递$TMPDIR/example.XXXXXXXX给mktemp或mkdir是危险的, 因为它可能会/example.XXXXXXXX在本地磁盘的根目录中产生(由于$ TMPDIR未被设置并成为空字符串)。

在OSX上,$TMPDIR始终设置为(至少在默认外壳程序中),而不是设置为/tmp(是的符号链接/private/tmp),而是设置为/var/folders/dx/*****_*************/T。因此,无论我们为OSX做些什么,都应该尊重这种默认行为。

总之,以下是我最终用来可靠地创建可在Linux和Darwin(Mac OS X)上使用的临时目录的内容,而无需对$TMPDIR或进行硬编码/tmp

mytmpdir=`mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir'`

第一部分是针对Linux的。在达尔文(Mac OS X)上,此命令将失败,错误状态代码1将以“用法:...”作为响应。这就是为什么我们忽略stderr而是执行Mac变体的原因。该mytmpdir前缀仅在Mac(需要设置该选项)上使用。


12
真的很酷 有时OS X的不同行为很烦人。
therealmarv

6
@therealmarv我总是想说。
Nikita Volkov

10
我刚mktemp -d在OS X 10.11.5 El Capitan上运行,它按预期运行file $(mktemp -d):: /var/folders/j4/htlnmbf97vlcdszj7_x8g0vh4k3_fp/T/tmp.JXmsrQnL: directory
Heath Borders

2
是的 您为这款Just Justed™感到惊讶。
Heath Borders

1
另外,如果您mktemp -d -t 'mytmpdir'在Linux上运行(已通过mktempfrom 进行了测试coreutils 8.26),则可以正常运行。

15

您必须提供一个模板。 mktemp -d /tmp/foo.XXXX应该管用。我从未见过--directory。这--表明它是GNU扩展。


6
如果要$TMPDIR在可用时使用,请执行mktemp -d "${TMPDIR:-/tmp}"/foo.XXXX。在Mac上可以使用bash,在Debian上可以使用dash,因此看起来可移植。
汤姆·安德森

9

更改--directory-d。前者是GNU-ism,但mktempcoreutils的GNU 也支持-d。在mktempOS X中是一样的,从BSD,所以-d应该是真正推出一款系统间漂亮便携mktemp的程序。


我只是尝试过mktemp -d,它也不起作用。
努力。

1
凯尔(Kyle)有完整的答案。在mktempOS X上需要一个模板。您使用的脚本采用GNU约定,如果未提供,则使用默认模板。
James Sneeringer,2012年

问题是unix期望XXXXX在模板中提供,因为OS X无法确定是否存在兼容的模板标志?
user3467349 '16

2
mktemp在OS X 10.11.5上,El Capitan为我工作file $(mktemp -d)::/var/folders/j4/htlnmbf97vlcdszj7_x8g0vh4k3_fp/T/tmp.JXmsrQnL: directory
Heath Borders

4
temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX")"
  • mktemp对于BSD(包括OSX)需要模板,但是它允许模板中包含任意数量的X
  • (GNU)mktempfor Linux不需要模板,但是,如果指定了模板,则Xs 的数量必须为6。

请注意,GNU-t已弃用该代码,因此将使用更适合未来的代码mktemp

temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX" 2>/dev/null || mktemp -q -d)"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.