8

当我尝试在 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 图形差异工具,而不是命令行工具,它已经很高兴从命令行使用多个管道。

-抢

4

4 回答 4

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
于 2012-10-01T18:43:51.523 回答
4

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

于 2012-10-01T14:14:40.840 回答
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 放在脚本的第一行。

于 2012-10-01T14:05:15.147 回答
0

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

于 2012-11-27T19:15:41.137 回答