Bash双进程替换提供了错误的文件描述符

时间:2012-10-01 14:01:07

标签: bash process pipe file-descriptor substitution

当我尝试在bash函数中引用两个进程替换管道时,只有引用的第一个管道工作。第二个给出了“错误的文件描述符”错误,如下所示:

$ foo(){
> cat "$1"
> cat "$2"
> }
$ foo <(echo hi) <(echo bye)
hi
cat: /dev/fd/62: Bad file descriptor
$ 

看来第二个管道在被引用时被丢弃,但是a)我似乎无法在任何文档中确认这种行为,并且b)我希望它不会。 =)

关于我做错的任何想法? FWIW我这样做是为了使包装器使用Mac OS X的FileMerge图形差异工具而不是命令行1,它已经很高兴从命令行使用多个管道。

-Rob

4 个答案:

答案 0 :(得分:7)

首先,我认为@Michael Krelin认为这与OS X(v3.2.48)提供的bash版本有关。从我的测试看起来好像文件描述符在函数执行第一个外部命令后被丢弃:

$ bar() { echo "Args: $*"; echo "First ext command:"; ls /dev/fd; echo "Second ext command:"; ls /dev/fd; }
$ bar <(echo hi) <(echo bye)
Args: /dev/fd/63 /dev/fd/62
First ext command:
0   1   2   3   4   5   6   62  63
Second ext command:
0   1   2   3   4   5   6

请注意,/ dev / fd / 62和63在两个ls列表之间消失。我想我找到了一个解决方法:将脆弱的fd复制到非脆弱的fd中,然后才有机会消失:

$ baz() { exec 3<"$1" 4<"$2"; ls /dev/fd; ls /dev/fd; cat /dev/fd/3; cat /dev/fd/4; }
$ baz <(echo hi) <(echo bye)
0   1   2   3   4   5   6   62  63
0   1   2   3   4   5   6
hi
bye

答案 1 :(得分:4)

OSX(3.2.48)提供的/bin/bash失败了。来自macports的那个(4.2.37 - 通常/opt/local/bin/bash,如果你安装它)工作正常。无论是版本还是构建我都不知道。也许你可能想要为这个脚本使用macports bash。一个肯定必须在每个mac上都有macports,所以我假设你这样做了: - )

答案 2 :(得分:2)

你确定你用bash运行它而不是其他shell吗?你检查了echo $SHELL的输出吗?

使用bash为我工作正常:

[16:03:51][tim@tim(1)]:~
(0)$function foo() { cat "$1"; cat "$2"; };
[16:03:59][tim@tim(1)]:~
(0)$foo <(echo "lva") <(echo hi)
lva
hi

当我将shebang更改为#!/ bin / dash时,我会收到错误。

请尝试将#!/ bin / bash作为一个shebang放在脚本的第一行。

答案 3 :(得分:0)

这看起来像这里的问题:http://bugs.alpinelinux.org/issues/1465