33

我想执行一个命令,让该命令的输出得到 gzip'd 的运行,并回显/发出该命令的输出。

即,类似:

echo "hey hey, we're the monkees" | gzip --stdout > my_log.gz

除了行执行时,我想在标准输出上看到这个:

hey hey, we're the monkees
4

4 回答 4

59

另一种方式(假设 shell 像bashor zsh):

echo "hey hey, we're the monkees" | tee >(gzip --stdout > my_log.gz)

公认的奇怪>()语法基本上执行以下操作:

  • 创建新的 FIFO(通常在 FIFO 中/tmp/
  • 在内部执行命令()并将 FIFO 绑定到该子命令上的标准输入
  • 将 FIFO 文件名返回到命令行。

那么tee,最终看到的是这样的:

tee /tmp/arjhaiX4

所有gzip看到的是它的标准输入。

对于 Bash,请参阅man bash详细信息。它在重定向部分。对于 Zsh,请参阅man zshexpn“进程替换”标题下。

据我所知,Korn Shell、经典 Bourne Shell 的变体(包括 ash 和 dash)以及 C Shell 不支持这种语法。

于 2009-02-20T20:05:32.997 回答
46
echo "hey hey, we're the monkees" | tee /dev/tty | gzip --stdout > my_log.gz

正如评论中指出的那样,/dev/stdout可能比/dev/tty在某些情况下效果更好。

于 2009-02-20T19:51:17.493 回答
19

喝杯漂亮的T恤

tee 命令将标准输入复制到标准输出以及作为参数给出的任何文件。当您不仅想通过管道发送一些数据,而且还想保存副本时,这很有用

当我度过一个缓慢的下午时,这里有一些精彩的说明性 ascii-art...

           +-----+                   +---+                  +-----+  
stdin ->   |cmd 1|    -> stdout ->   |tee|   ->  stdout  -> |cmd 2|
           +-----+                   +---+                  +-----+
                                       |
                                       v
                                     file

正如 grayfade 在另一个答案中所展示的那样,“文件”不必是常规文件,而可以是 FIFO,让您将 tee 的输出通过管道传输到第三个命令中。

           +-----+                   +---+                  +-----+  
stdin ->   |cmd 1|    -> stdout ->   |tee|   ->  stdout  -> |cmd 2|
           +-----+                   +---+                  +-----+
                                       |
                                       v
                                     FIFO
                                       |
                                       v
                                    +-----+
                                    |cmd 3|
                                    +-----+
于 2009-02-20T19:53:38.953 回答
6

只是发布一种不涉及触摸磁盘的方式:

echo "hey hey, we're the monkees" | (exec 1>&3 && tee /proc/self/fd/3 | gzip --stdout > my_log.gz)
于 2010-01-04T22:52:09.627 回答