将多个标准输出重定向

3
我有一个文件夹,里面有三个文件,分别名为One、Two、Three。
其中One文件包含:
asdfg

两个包含:
qwerty

三包含:
zxcvb

当我输入以下命令时:
$ls > One > Two > Three

然后我下达以下指令:
$cat One

输出:

Nothing

然后我下达以下命令:
$cat Two

输出:

Nothing

然后我下达以下命令:
$cat Three

输出:

One
Three
Two

有人可以请详细说明一下这里到底发生了什么吗?为什么文件One和Two会变为空,以及为什么ls命令的输出只被写入到文件Three中呢?

我们只能猜测你的真实意图。请编辑您的问题以包括预期的输出。祝好运。 - shellter
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 一直在覆盖同一个文件描述符,因此只有最后一个描述符会接收到任何数据。一个解决方法是使用 tee 命令,它将 stdin 收到的内容写入所有参数和 stdout

ls | tee One Two Three > /dev/null 

顺便提一下,zsh也支持此功能:

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

2

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

您似乎在寻找tee命令。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接