如何将标准输入用作文件

doe*_*man 11 osx bash zsh shell-script stdin

我有一个命令需要一个文件作为输入,但我从其中获取输入stdin,并且不想创建临时文件。

我想做以下事情:

#!/bin/bash
osadecompile /dev/stdin < input_file.scpt
Run Code Online (Sandbox Code Playgroud)

但这会导致 I/O 错误。以下方法可行,但是不使用临时中间文件是否可能?

#!/bin/bash
AS_FILE=$(mktemp)
cat - > "$AS_FILE"
osadecompile "$AS_FILE"
rm "$AS_FILE"
Run Code Online (Sandbox Code Playgroud)

正如您可能已经猜到的,我使用的是bash 3.2的 macOS 。然而,zsh 5.3解决方案也将受到欢迎。

Sté*_*las 8

使用zsh,您可以执行以下操作:

\n
cmd =(cat)\n
Run Code Online (Sandbox Code Playgroud)\n

哪里=(...)是第三种形式的进程替换,它使用临时文件而不是管道。

\n

对于bash5.1 或 之前的版本zsh,对于不以空行结尾的输入(以及在不包含 NUL 字节的 bash 中),您可以执行以下操作:

\n
cmd /dev/fd/3 3<<< "$(cat)"\n
Run Code Online (Sandbox Code Playgroud)\n

正如此处字符串(来自 zsh)一样,此处文档(来自 Bourne shell)是通过 bash\xc2\xb9 和 zsh 中的(已删除的)临时文件实现的。在 macOS(而不是 Linux)上,假设cmd只打开文件一次(不过可以在其中自由查找),因为每个开口都会从文件中与前一个开口相同的位置开始,这可能会造成混淆,cmd如果它假设该位置位于文件的开头。

\n
\n

\xc2\xb9 请注意,bash 行为在 5.0 中发生了变化,bash 开始不遗余力地使临时文件不可写,而在 5.1 中,bash 改用管道而不是小文件的临时文件

\n