将stdout传递给多个进程[zsh]

时间:2011-02-14 17:45:10

标签: pipe zsh

我知道zsh能够做到:

ls -1 >foo >bar

但是,假设我想通过另一个命令运行两个输出。例如,我如何组合这两个命令以避免两次运行mysqldump

mysqldump db1 | bzip2 > db1.sql.bz2
mysqldump db1 | mysql db2

我能提出的最接近的是:

mysqldump db1 >db1.sql | mysql db2
bzip2 db1.sql

但是我宁愿不将文件写入未压缩的磁盘(它很大!)。

3 个答案:

答案 0 :(得分:6)

您可以使用流程替换。

在zsh中:

ls -1 > >(grep foo) > >(grep bar)

在bash中:

ls -1 | tee >(grep foo) >(grep bar) >/dev/null

进程替换为您管理命名管道。

答案 1 :(得分:5)

以下作品:

echo abc > >(gzip > 1) > >(xz > 2)

为您的示例修改(但未经测试):

mysqldump db1 > >(bzip2 > db1.sql.bz2) > >(mysql db2)

或者,可能更好:

{ mysqldump db1 } > >(bzip2 > db1.sql.bz2) > >(mysql db2)

//我在man zshexpn中的PROCESS SUBSTITUTION部分找到了几乎相同的例子:

  

另请注意,前一个示例可以更紧凑,更有效地编写(如果设置了MULTIOS选项):

   paste <(cut -f1 file1) <(cut -f3 file2) \
   > >(process1) > >(process2)
     

在上面的例子中,shell使用管道而不是FIFO来实现后两个进程替换。

     

&gt;(进程)还有一个问题;当它附加到外部命令时,父shell不会等待进程完成,因此紧接着的命令不能依赖于结果完成。问题和解决方案与zshmisc(1)中的MULTIOS部分中描述的相同。因此,在上面的例子的简化版本中:

   paste <(cut -f1 file1) <(cut -f3 file2) > >(process)
     

(请注意,不涉及MULTIOS),进程将异步运行。解决方法是:

   { paste <(cut -f1 file1) <(cut -f3 file2) } > >(process)
     

这里的额外进程是从父shell生成的,它将等待它们的完成。

答案 2 :(得分:1)

您可以通过fifo连接进程并使用tee实用程序将标准输出复制到每个fifo和stdout。类似的东西:

mkfifo db1.sql
bzip2 db1.sql &
mysqldump db1 | tee db1.sql | mysql db2