In process substitution I can see two syntaxes:




Often I use the second syntax. But I have no idea what is exactly the difference between the two? searching about that yields nothing special.

  • 1
    To whom downvoted, please drop a comment to explain what's wrong with my question. Sep 14, 2020 at 12:56
  • I didn't vote on your question, but one thing that stands out is that Bash's manual (man 1 bash or, more specifically, info bash "process substitution") explains the meaning of the two forms. Sure, knowing about the documentation and how to search through it is not trivial, but some users probably expect it from question askers.
    – fra-san
    Sep 14, 2020 at 13:11
  • @fra-san: Thanks for pointing that. As you can see I have added the link to the documentation, but it didn't mention the difference between the two. Sep 14, 2020 at 13:12
  • 1
    The link you added is not the documentation, that's some guide written by some guy on the internet. The documentation, as displayed by info bash "process substitution" can be found online as well on the GNU official website Sep 14, 2020 at 13:39
  • 1
    If on Debian or derivative, you may need to install a bash-doc package. Sep 14, 2020 at 13:51

1 Answer 1


You use:

consumer <(feeder)

For the output of feeder to be fed to consumer, when consumer cannot take its input from stdin (in which case you'd simply use feeder | cousumer) but only from file names given as argument.

In that case, feeder's output is the writing end of a pipe, and the expansion of <(feeder) is a filename (usually /dev/fd/<x>, though could be a named pipe on systems that don't support /dev/fd/<n>) which once open (by consumer) gets you to the reading end of that pipe.

Symmetrically, you use:

feeder >(consumer)

For those feeder commands that don't send their output to stdout (where you could just do feeder | consumer again), but to a file whose name you need to pass as argument.

Then consumer's input is the reading end of a pipe, and >(consumer) expands to a filename which once opened (by feeder) gets you to the writing end of that pipe.

It's more common to use <(...) because it's useful in commands that take more than one input like:

diff -u <(cmd1) <(cmd2)

While it's less common for commands to produce more than one output, or for commands not to be able to send their output to stdout. A common exception is:

feeder | tee >(consumer1) >(consumer2) | consumer3

Where tee is a typical command that sends some output to more than one file (in addition to stdout) in parallel.

You may have seen things like:

tar cf - somedir |
 gzip -9 |
 tee >(shasum > dir.tgz.shasum) >(md5sum > dir.tgz.md5sum) > dir.tgz

To send the output of gzip (here a compressed tar archive) to the output file as well as shasum and md5sum to generate and store the checksums at the same time.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .