4

In bash, I want to assign my current working directory to a variable. Using a subshell, I can do this.

var=$(pwd)

echo $var
/home/user.name

If I use process substitution like so:

var=<(pwd)

echo $var
/dev/fd/63

I have understood that process substitution is primarily used when a program does not accept STDIN. It is unclear to me what a process substitution exactly does and why it assigns /dev/fd/63 to var.

4

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 command substitution has finished executing (when the echo 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:

$ echo $( t=1234; echo $t )
1234
$ echo $t
(no output)

Here, echo gets 1234 as a string argument from the command substitution.

$ cat <( t=4321; echo $t )
4321
$ echo $t
(no output)

Here, cat get the filename of a file (named pipe/file descriptor) as its argument. The file contains the data 4321.

  • I see, that makes sense. Given what you explained, I assume the outputs of the commands called in the process substitution brackets are being stored somewhere temporarily and then being read in by the commands that read from these files? If so, where is this temporary folder? – PejoPhylo Sep 20 '17 at 8:31
  • @PejoPhylo See update. There is a directory called /dev/fd that holds file descriptors (handles for open files, named by integers, number 1 is stdout, 2 is stderr and 0 is stdin, for example). In you example, file descriptor 63 will hold your data. This is not a regular file, but acts like a FIFO or named pipe. You ordinarily do not poke around in /dev/fd yourself. – Kusalananda Sep 20 '17 at 8:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.