我知道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
但是我宁愿不将文件写入未压缩的磁盘(它很大!)。
答案 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