Process substitution is the counterpart to command substitution. Command substitution sets a variable to the result of a command, as in dir_contents=`ls -al` or xref=$( grep word datafile). Process substitution feeds the output of a process to another process (in other words, it sends the results of a command to another command).
>(command)
<(command)
These initiate process substitution. This uses /dev/fd/<n> files to send the results of the process within parentheses to another process. [1]
![]() | There is no space between the the "<" or ">" and the parentheses. Space there would give an error message. |
bash$ echo >(true) /dev/fd/63 bash$ echo <(true) /dev/fd/63 |
cat <(ls -l) # Same as ls -l | cat sort -k 9 <(ls -l /bin) <(ls -l /usr/bin) <(ls -l /usr/X11R6/bin) # Lists all the files in the 3 main 'bin' directories, and sorts by filename. # Note that three (count 'em) distinct commands are fed to 'sort'. diff <(command1) <(command2) # Gives difference in command output. tar cf >(bzip2 -c > file.tar.bz2) $directory_name # Calls "tar cf /dev/fd/?? $directory_name", and "bzip2 -c > file.tar.bz2". # # Because of the /dev/fd/<n> system feature, # the pipe between both commands does not need to be named. # # This can be emulated. # bzip2 -c < pipe > file.tar.bz2& tar cf pipe $directory_name rm pipe # or exec 3>&1 tar cf /dev/fd/4 $directory_name 4>&1 >&3 3>&- | bzip2 -c > file.tar.bz2 3>&- exec 3>&- # Thanks, S.C. |
A reader of this document sent in the following interesting example of process substitution.
# Script fragment taken from SuSE distribution:
while read des what mask iface; do
# Some commands ...
done < <(route -n)
# To test it, let's make it do something.
while read des what mask iface; do
echo $des $what $mask $iface
done < <(route -n)
# Output:
# Kernel IP routing table
# Destination Gateway Genmask Flags Metric Ref Use Iface
# 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo
# As S.C. points out, an easier-to-understand equivalent is:
route -n |
while read des what mask iface; do # Variables set from output of pipe.
echo $des $what $mask $iface
done # Same output as above. |
| [1] | This has the same effect as a named pipe (temp file), and, in fact, named pipes were at one time used in process substitution. |