为什么 BASH 进程替换不适用于某些命令?

为什么 BASH 进程替换不适用于某些命令?

有时,进程替换不会按预期工作。这是一个例子:

输入:

gcc <(echo 'int main(){return 0;}')

输出:

/dev/fd/63: file not recognized: Illegal seek
collect2: error: ld returned 1 exit status

输入:

但当与不同的命令一起使用时,它会按预期工作:

grep main <(echo 'int main(){return 0;}')

输出:

int main(){return 0;}

我注意到其他命令有类似的失败(即期望进程替换中的文件的命令无法使用/dev/fd/63或类似)。这次失败gcc只是最近的一次。是否有一些我应该注意的一般规则来确定进程替换何时会以这种方式失败并且不应使用?

我在 Ubuntu 12.04 上使用这个 BASH 版本(我也在 arch 和 debian 中看到过这个):
GNU bash, version 4.3.11(1)-release (i686-pc-linux-gnu)

答案1

进程替换会产生一个特殊文件(如/dev/fd/63您的示例中),其行为类似于命名管道的读取端。该文件可以打开和读取,但不能写入,也不能查找。

将参数视为纯流的命令可以工作,而期望在给定的文件中查找(或写入文件)的命令则不起作用。有效的命令类型通常被认为是过滤器:catgrepsedgzipawk等...无效命令的一个示例是诸如 之类的编辑器vi或诸如 之类的文件操作mv

gcc希望能够对其输入文件执行随机访问,以检测它们是用什么语言编写的。如果您提供gcc有关输入文件语言的提示,它很乐意流式传输文件:

gcc -x c <(echo 'int main(){return 0;}')

无需过程替换的更简单、更直接的形式也有效:

echo 'int main(){return 0;}' | gcc -x c -

请注意,这并不特定于bash.所有支持进程替换的 shell 的行为方式都相同。

相关内容