3

我在一个名为一、二、三的目录中有三个文件。

一个包含:

asdfg

两个包含:

qwerty

三包含:

zxcvb

当我给出以下命令时:

$ls > One > Two > Three

然后我给出以下命令:

$cat One

输出:

Nothing

然后我给出以下命令:

$cat Two

输出:

Nothing

然后我给出以下命令:

$cat Three

输出:

One
Three
Two

任何人都可以阐明这里发生了什么吗?为什么文件一和二变成空,为什么 ls 命令的输出只写入文件三?

4

2 回答 2

3

如前所述,这里 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 不断覆盖相同的文件描述符。所以只有最后一个会收到任何数据。一种解决方法是使用teewhich 将接收stdin到的内容写入其所有参数和stdout

ls | tee One Two Three > /dev/null 

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

 zsh$ setopt multios
 zsh$ ls > One > Two > Three
于 2012-09-15T19:14:06.870 回答
2

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

您似乎正在寻找tee命令。

于 2012-09-15T19:09:02.830 回答