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/mkfifo)tee
并在命名管道上读取命令。
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
正常终止。
Gil*_*il' 15
如果我理解正确,您正在寻找等效的tee file1 file2 file3
, 但不是将相同的数据写入三个文件file1
, file2
and file3
,您希望将相同的数据通过管道传输到三个命令中cmd1
, cmd2
and 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
到标准输出并且另外运行cmd1
以hello
作为输入。
因此,例如,如果您想复制 的输入somecommand
并将其传递给cmd1
and cmd2
,您可以使用
somecommand | tee >(cmd1) | cmd2
Run Code Online (Sandbox Code Playgroud)
如果您的 shell 不支持进程替换,您可以改用命名管道。请参阅Arcege 的答案以了解其工作原理。命名管道不如进程替换方便,因为您必须创建和删除它们,并手动启动和同步进程。它们具有完全可移植的优点,但并非所有 shell 都支持进程替换。它们还可以用于进程替换以外的场景。
在幕后,在某些系统上,进程替换在内部使用命名管道。但是,在大多数系统上,它依赖于表示文件描述符的命名文件。
至少在bash 中,您可以跳过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)