修复或替代 OS X 中的 mktemp

sou*_*ped 85 osx utilities shell-script

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

TEMP=`mktemp --directory`
Run Code Online (Sandbox Code Playgroud)

但是,这条线在我的机器上不起作用(OS X 10.6)。

我将如何修复这条线,使其与跨 un*x-like-platform 兼容?编辑:替代命令也足够了。

Tim*_*hof 128

以下是我最终用来可靠地创建一个适用于 Linux 和 Darwin(Mac OS X 10.11 之前的所有版本)的临时目录的内容,无需硬编码$TMPDIR/tmp

mytmpdir=$(mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir')
Run Code Online (Sandbox Code Playgroud)

背景:

GNU mktemp 命令不需要参数。Plainmktemp将工作并在系统的临时目录中创建一个临时文件。

Plainmktemp -d将创建一个目录而不是一个文件,这是您希望在 Linux 上使用的。

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

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

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

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

在 OSX 上,$TMPDIR始终设置并且(至少在默认 shell 中)它没有设置为/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')
Run Code Online (Sandbox Code Playgroud)

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

  • 真的很酷。有时 OS X 不同的行为很烦人。 (14认同)
  • 我刚刚在 OS X 10.11.5 El Capitan 上运行了 `mktemp -d`,它按预期工作: `file $(mktemp -d)`: `/var/folders/j4/htlnmbf97vlcdszj7_x8g0vh4k3_fp/T/tmp.JXmsrQnL: directory ` (12认同)
  • @therealmarv 我宁愿说,总是。 (6认同)
  • 我的 OSX (10.14.5 Mojave) 的手册页显示“如果未传递任何参数或仅传递 -d 标志,则 mktemp 的行为就像提供了 -t tmp 一样。” (4认同)
  • 是的。我和您一样惊讶于这个 Just Work™。 (2认同)
  • OS X 10.11 El Capitan ([shell_cmds-187](https://github.com/apple-oss-distributions/shell_cmds/tree/shell_cmds-187)) 是第一个版本,其中 [`mktemp`](https:// github.com/apple-oss-distributions/shell_cmds/blob/shell_cmds-187/mktemp/mktemp.c) 如果没有给出参数,则选择 `tmp` 作为模板。 (2认同)

Kyl*_*nes 15

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

  • 如果您想在可用时使用 `$TMPDIR`,请执行 `mktemp -d "${TMPDIR:-/tmp}"/foo.XXXX`。这适用于 Mac 上的 bash 和 Debian 上的 dash,所以它看起来很便携。 (6认同)

Jam*_*ger 8

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

  • OS X 10.11.5 El Capitan 上的 `mktemp` 对我有用:`file $(mktemp -d)`:`/var/folders/j4/htlnmbf97vlcdszj7_x8g0vh4k3_fp/T/tmp.JXmsrQnL: directory` (2认同)

go2*_*ull 6

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

请注意GNU-t已弃用,因此更面向未来的代码将是mktemp

temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX" 2>/dev/null || mktemp -q -d)"
Run Code Online (Sandbox Code Playgroud)