A command substitution ($(...)
) will be replaced by the output of the command, while a process substitution (<(...)
) will be replaced by a filename from which the output of the command may be read. The command, in both instances, will be run in a subshell.
In your case, the output from pwd
in <(pwd)
may be found at /dev/fd/63
. This file ceases to exist as soon as the command that uses the process substitution has finished executing (when the assignment to var
in your example is done).
The filename returned by a process substitution is the name of a file descriptor or named pipe, not a regular file:
Process substitution is supported on systems that
support named pipes (FIFOs) or the /dev/fd
method of naming open files.
A common use of process substitution is to pre-sort files for the join
command:
$ join <( sort file1 ) <( sort file2 )
or for removing columns from a file (here, column 2 is removed from a tab-delimited file by using cut
twice and paste
to stitch the result together):
$ paste <( cut -f 1 file ) <( cut -f 3- file )
Process substitution is more or less a syntactical shortcut for avoiding using temporary files explicitly.
Both command substitutions and process substitutions are performed in subshells. The following shows that the environment in these subshells do not affect the parent shell's environment:
$ unset t
$ echo "$( t=1234; echo "$t" )"
1234
$ echo "$t"
(empty line output)
Here, echo
gets 1234
as a string argument from the command substitution.
$ unset t
$ cat <( t=4321; echo "$t" )
4321
$ echo "$t"
(empty line output)
Here, cat
get the filename of a file (named pipe/file descriptor) as its argument. The file contains the data 4321
.