是否可以将一个命令的输出重定向到多个命令中?

Abd*_*red 21 command-line pipe tee

据我所知,我可以使用 tee 命令将标准输出拆分到屏幕和其他文件上:

command -option1 -option2 argument | tee file1 file2 file3 
Run Code Online (Sandbox Code Playgroud)

是否可以使用 tee 将输出重定向到命令而不是文件,以便理论上我可以创建命令链?

Arc*_*ege 24

您可以在命令行上使用命名管道(http://linux.die.net/man/1/mkfifotee并在命名管道上读取命令。

mkfifo /tmp/data0 /tmp/data1 /tmp/data2
cmd0 < /tmp/data0 & cmd1 < /tmp/data1 & cmd2 < /tmp/data2 &
command -option1 -option2 argument | tee /tmp/data0 /tmp/data1 /tmp/data2
Run Code Online (Sandbox Code Playgroud)

command完成时,tee将关闭命名管道,这将用信号在每个的EOF(读取的0字节)/tmp/dataN,这通常终止cmdN进程。真实例子:

$ mkfifo /tmp/data0 /tmp/data1 /tmp/data2
$ wc -l < /tmp/data0 & wc -w < /tmp/data1 & wc -c < /tmp/data2 &
$ tee /tmp/data0 /tmp/data1 /tmp/data2 < /etc/passwd >/dev/null
$ 61
1974
37
Run Code Online (Sandbox Code Playgroud)

由于后台进程,shell 在程序输出之前返回了一个提示。所有三个实例都wc正常终止。

  • 可能想要将 /dev/data0 更改为 /tmp/data0。另外,感谢您以与 shell 无关的方式回答问题。这比假设每个人都使用 bash 更有帮助。 (2认同)

Gil*_*il' 15

如果我理解正确,您正在寻找等效的tee file1 file2 file3, 但不是将相同的数据写入三个文件file1, file2and file3,您希望将相同的数据通过管道传输到三个命令中cmd1, cmd2and cmd3, 即

… | ??? cmd1 cmd2 cmd3
Run Code Online (Sandbox Code Playgroud)

应该相当于

… | cmd1 &
… | cmd2 &
… | cmd3 &
Run Code Online (Sandbox Code Playgroud)

除了只会执行一次。

有两种方法可以做到这一点。

Ksh93、bash 和 zsh 支持进程替换。这是管道的泛化,它允许命令的参数是一个文件,该文件在写入时将数据作为输入传递给命令(还有输入变量,当从中读取时,获得命令输出的数据) . 那是,

echo hello | tee >(cmd1)
Run Code Online (Sandbox Code Playgroud)

打印hello到标准输出并且另外运行cmd1hello作为输入。

因此,例如,如果您想复制 的输入somecommand并将其传递给cmd1and cmd2,您可以使用

somecommand | tee >(cmd1) | cmd2
Run Code Online (Sandbox Code Playgroud)

如果您的 shell 不支持进程替换,您可以改用命名管道。请参阅Arcege 的答案以了解其工作原理。命名管道不如进程替换方便,因为您必须创建和删除它们,并手动启动和同步进程。它们具有完全可移植的优点,但并非所有 shell 都支持进程替换。它们还可以用于进程替换以外的场景。

在幕后,在某些系统上,进程替换在内部使用命名管道。但是,在大多数系统上,它依赖于表示文件描述符的命名文件

  • 另请参阅“moreutils”中的“pee”。 (5认同)

Tob*_*ler 6

至少在您可以跳过mkfifo使用进程替换:

command -option1 -option2 argument | tee >(cmd1) >(cmd2) >(cmd3)
Run Code Online (Sandbox Code Playgroud)

或采用Arcege的例子

tee >(wc -l) >(wc -w) >(wc -c) < /etc/passwd >/dev/null
Run Code Online (Sandbox Code Playgroud)