开发者

Pipe stdout to multiple processes [zsh]

开发者 https://www.devze.com 2023-02-10 16:01 出处:网络
I\'m aware of the ability for zsh to do: ls -1 >foo >bar But let\'s say I want to run both outputs through another command. For instance, how would I combine these two co开发者_运维百科mmands

I'm aware of the ability for zsh to do:

ls -1 >foo >bar

But let's say I want to run both outputs through another command. For instance, how would I combine these two co开发者_运维百科mmands so as to avoid running mysqldump twice?

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

The closest I can come up with is:

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

But I'd rather not write the file to disk uncompressed (it's big!).


The following works:

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

Modified for your example (but untested):

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

or, probably better:

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

// I found almost the same example in PROCESS SUBSTITUTION section in man zshexpn:

Also note that the previous example can be more compactly and efficiently written (provided the MULTIOS option is set) as:

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

The shell uses pipes instead of FIFOs to implement the latter two process substitutions in the above example.

There is an additional problem with >(process); when this is attached to an external command, the parent shell does not wait for process to finish and hence an immediately following command cannot rely on the results being complete. The problem and solution are the same as described in the section MULTIOS in zshmisc(1). Hence in a simplified version of the example above:

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

(note that no MULTIOS are involved), process will be run asynchronously. The workaround is:

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

The extra processes here are spawned from the parent shell which will wait for their completion.


You can use process substitution.

In zsh:

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

In bash:

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

Process substitution manages named pipes for you.


You can connect processes through fifo's and use tee utility to copy the standard output to each fifo and to stdout. Something like:

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

精彩评论

暂无评论...
验证码 换一张
取 消