It should be noted that process substitution is not limited to the form <(command)
, which uses the output of command
as a file. It can be in the form >(command)
which feeds a file as the input to command
as well. This is also mentioned in the quote of bash manual in @enzotib's answer.
For the date | cat
example above, a command that uses the process substitution of the form >(command)
to achieve the same effect would be,
date > >(cat)
Note that the >
before >(cat)
is necessary. This can again be clearly illustrated by echo
as in @Caleb's answer.
$ echo >(cat)
/dev/fd/63
So, without the extra >
, date >(cat)
would be the same as date /dev/fd/63
which will print a message to stderr.
Suppose you have a program that only takes filenames as parameters and does not process stdin
or stdout
. I will use the oversimplified script psub.sh
to illustrate this. The content of psub.sh
is
#!/bin/bash
[ -e "$1" -a -e "$2" ] && awk '{print $1}' "$1" > "$2"
Basically, it tests that both of its arguments are files (not necessarily regular files) and if this is the case, write the first field of each line of "$1"
to "$2"
using awk. Then, a command that combines all that mentioned so far is,
./psub.sh <(printf "a a\nc c\nb b") >(sort)
This will print
a
b
c
and is equivalent to
printf "a a\nc c\nb b" | awk '{print $1}' | sort
but the following will not work, and we have to use process substitution here,
printf "a a\nc c\nb b" | ./psub.sh | sort
or its equivalent form
printf "a a\nc c\nb b" | ./psub.sh /dev/stdin /dev/stdout | sort
If ./psub.sh
also reads stdin
besides what is mentioned above, then such an equivalent form does not exist, and in that case there are nothing we can use instead of the process substitution (of course you can also use a named pipe or temp file, but that's another story).