I feel pipeline is good at gradually processing data step by step by sequence the commands one by one; process substitution is good at getting outputs from many command sequences or provide inputs to many command sequences by files; combine them appropriately could be some powerful tools.
Pipeline use a pipe to link two file descriptors, typically standard output file descriptor of a command, and standard input file descriptor of the next command, thus the output of a command can be accessed by the command next to it. You can sequence infinite commands in this way to gradually process the data.
ls | head -3 | tail -1
The output of ls is used as the input of head; the output of head is used as the input of tail.
Process Substitution creates a file by which other commands can access the output of a command sequence or provide input to it.
paste <(echo hello) <(echo world) | tee >(cat) >(cat)
<(echo hello) and <(echo world) created two files as the input of paste, one file includes 'hello', one includes 'world', the output of the echo commands;
tee reads the output ('hello world'
) of paste through the pipe;
the two >(cat) commands also create two files as the input of the two cat commands, two files all include 'hello world'
which is written by the command tee;
then the two cat commands output the content of the files they get as their input.
The output is as below:
# paste <(echo hello) <(echo world) | tee >(cat) >(cat)
hello world
hello world
hello world
First 'hello world'
is output of the paste
command; The two after it is output of the two cat commands.
The file is created by <() includes output of the command sequence as its content; but the file created by >() is empty, you must write something to it explicitly.
➜ Downloads echo hello >(cat)
hello /proc/self/fd/12
➜ Downloads echo hello > >(cat)
hello
Above, first time the 'hello' is produced by the echo command; because the file created by >(cat) is empty, so the name of the file is produced by the shell.
Second time, the 'hello' is redirected to the file created by >(cat), then the file is taken as the input of the cat command which produces the 'hello'.
More examples:
comm -23 <(set -o posix; set | sort) <(env | sort)
Comparing the difference between shell variables and environmental variables.
References:
https://www.gnu.org/software/bash/manual/html_node/Pipelines.html
https://www.gnu.org/software/bash/manual/html_node/Process-Substitution.html
https://man7.org/linux/man-pages/man2/pipe.2.html