重定向多个标准输出

时间:2012-09-15 18:57:15

标签: bash redirect stdout

我在一个名为One,Two,Three的目录中有三个文件。

一个包含:

asdfg

两个包含:

qwerty

三个包含:

zxcvb

当我发出以下命令时:

$ls > One > Two > Three

然后我给出以下命令:

$cat One

输出:

Nothing

然后我给出以下命令:

$cat Two

输出:

Nothing

然后我给出以下命令:

$cat Three

输出:

One
Three
Two

任何人都可以了解这里发生的事情吗?为什么文件One&两个变为空,为什么ls命令的输出只写入文件Three?

2 个答案:

答案 0 :(得分:3)

如前所述here bash不支持多路分解,也不支持多路复用。您看到的效果是每个文件都被打开O_TRUNC,这意味着所有内容都被销毁。当指定多个重定向时,它们会立即再次关闭,只保留最后一个重定向并实际接收任何数据。

以下是strace运行命令的摘录:

strace -f -e open,dup2,close bash -c 'ls > one > two > three'
...
open("one", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3
dup2(3, 1)                  = 1
close(3)                    = 0
open("two", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3
dup2(3, 1)                  = 1
close(3)                    = 0
open("three", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3
dup2(3, 1)                  = 1
close(3)                    = 0
...

正如您所看到的,bash会覆盖相同的文件描述符。所以只有最后一个会收到任何数据。一种解决方法是使用teestdin收到的内容写入其所有参数和stdout

ls | tee One Two Three > /dev/null 

在旁注中,zsh确实支持这一点:

 zsh$ setopt multios
 zsh$ ls > One > Two > Three

答案 1 :(得分:2)

您只能重定向一次。第一个重定向打开第一个写入文件(删除任何以前的内容),然后在下一个重定向覆盖它时立即关闭它。

您似乎在寻找tee命令。