我在一个名为One,Two,Three的目录中有三个文件。
一个包含:
asdfg
两个包含:
qwerty
三个包含:
zxcvb
当我发出以下命令时:
$ls > One > Two > Three
然后我给出以下命令:
$cat One
输出:
Nothing
然后我给出以下命令:
$cat Two
输出:
Nothing
然后我给出以下命令:
$cat Three
输出:
One
Three
Two
任何人都可以了解这里发生的事情吗?为什么文件One&两个变为空,为什么ls命令的输出只写入文件Three?
答案 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会覆盖相同的文件描述符。所以只有最后一个会收到任何数据。一种解决方法是使用tee
将stdin
收到的内容写入其所有参数和stdout
:
ls | tee One Two Three > /dev/null
在旁注中,zsh
确实支持这一点:
zsh$ setopt multios
zsh$ ls > One > Two > Three
答案 1 :(得分:2)
您只能重定向一次。第一个重定向打开第一个写入文件(删除任何以前的内容),然后在下一个重定向覆盖它时立即关闭它。
您似乎在寻找tee
命令。