为什么某些命令无法使用BASH进程替换?


29

有时,流程替换将无法按预期进行。这是一个例子:

输入:

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,版本4.3.11(1)-release(i686-pc-linux-gnu)


1
illegal seek貌似答案-在|pipebash点执行的程序是不是可搜索的文件。可能如果您无法成功echo data | command /dev/fd/0完成某个程序,那么您将拥有类似的运气<(cmd)。它不提供磁盘文件-只是替换了一个指向管道文件描述符的参数。
mikeserv 2014年

2
在这种特殊情况下,尽管gcc 可以接受标准输入,但它(默认情况下)使用文件扩展名来确定语言。因此,尝试gcc -xc <(echo 'int main(){return 0;}')(将语言C显式设置)。
钢铁司机

我被引导到这里是为了回答我自己的问题,这可能是另一个例子。superuser.com/questions/1243405。感谢您比我更好地表述这个问题。
乔纳森·哈特利

Answers:


33

进程替换会生成一个特殊的文件(如/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。所有支持进程替换的外壳的行为都相同。


+1可以解决gcc的问题,但是我不确定您对文件的看法。<()就所有意图和目的而言,格式应像文件一样。实际上,我不知道有任何命令期望文件不满意<()。不起作用的是那些需要文件而不是文件的文件。例如,grep -f需要一个文件并与配合使用<()
terdon

4
@terndon确定<()会产生一个文件(该结构/proc/self/fd/something在我的系统上扩展为)。此名称在打开时的作用类似于支持和其他对象(但不是S_IFIFO)的命名管道()而不是常规文件(S_IFREG)的读取端。read()seek()
Celada 2014年

7
需要注意的是zsh支持进程替换的第三形式使用临时文件特别是用于这一目的:gcc =(echo 'int main(){return 0;}')
斯特凡Chazelas

也许有关系,但与<(echo '...')但不合作<(git show ...)。知道为什么会这样吗?
乔恩赫斯

2
GCC不会“对其输入文件执行随机访问以检测它们所使用的语言”。它只是查看文件名的扩展名。如果文件名没有扩展名(或者如果文件名没有扩展名),则GCC会假定该文件是目标文件或链接描述文件,并将其传递给ld(它会检测目标格式)。-x不是暗示;这是一个声明。如果指定-x f95,则GCC会将文件传递给Fortran-95编译器,而不管其名称或内容如何。参见gcc.gnu.org/onlinedocs/gcc-8.1.0/gcc/Overall-Options.html
rici
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.