【问题标题】:Simple shell. Mixed pipes and output简单的外壳。混合管道和输出
【发布时间】:2023-09-21 18:31:01
【问题描述】:

让我们考虑一下:

 cat > outout.txt | cat > outout2.txt 

我不知道如何解释这样的事情。第二个命令的输入是什么?

【问题讨论】:

  • 如果您想同时使用这两个文件,请查看“tee”。

标签: linux shell pipe


【解决方案1】:

当 cat 没有收到文件名参数时,它会从 STDIN 获取输入并将其发送到 STDOUT,因此命令链的第一部分的作用是将输入的任何内容(直到 EOD)放入文件输出。 txt:

cat > outout.txt

如果一切正常,此命令不会产生任何输出,因此命令链的第二部分没有任何内容可放入 outout2.txt:

cat > outout2.txt

所以文件 outout2.txt 被完整的命令链清空:

$ cat > outout.txt | cat > outout2.txt

但请注意,如果第一个“cat”调用生成输出,则 outout2.txt 获得一些输出。例如,如果 outout.txt 无法修改,我们将 STDERR 输出发送到 STDOUT:

$ chmod a-w outout.txt
$ cat 2>&1 > outout.txt | cat > outout2.txt

然后 outout.txt 将为空,但以下文本将写入 outout2.txt(消息的确切文本可能取决于您的 shell - 我使用的是 bash 3.2):

-bash: outout.txt: Permission denied

【讨论】:

  • 从技术上讲,它不是第一个生成错误消息的cat,而是由执行cat 的管道创建的子shell。一旦 shell 无法打开outout.txt,第一个cat 将永远不会运行。
  • 另外,outout2.txt 没有改变;无论管道中发生什么其他情况,它都会被 > 运算符截断。
  • @chepner,关于 outout2.txt 的内容被覆盖,你当然是对的,我已经更正了我的答案。至于错误信息的来源,我写的是“first cat invocation”产生的,意思是“cat 2>&1>outout.txt”,当然是这两个中的第一个正在执行的命令管道符号暗示的子壳。在谈论命令行操作时,通常会忽略“命令”和“运行命令的 shell”之间的区别。
【解决方案2】:

好吧,让我们试试吧:

$ echo "hello" | cat > outout.txt | cat > outout2.txt 
$ cat outout.txt 
hello
$ cat outout2.txt 

看来,对于 bash,> 重定向的优先级高于管道。

【讨论】:

    【解决方案3】:

    在处理输出重定向之前设置管道。创建了两个子shell,每个子shell 都从父shell 继承其文件。第一个子shell 的标准输出用作第二个子shell 的标准输出。但是,第一个cat 不使用它继承的文件进行标准输出;它使用outout.txt。结果,没有任何内容写入第二个cat 的标准输入,因此它在第一次读取时检测到文件结尾并退出而不向outout2.txt 写入任何内容。第一个cat的标准输入按预期写入outout.txt

    【讨论】: