By doing
tee >(some_command)
bash creates a subshell to run some_command . The stdin assigned half the pipe reading. bash leaves the name of this channel on the command line, so tee will pump its input into the pipe. The subshell stdout and stderr remain unchanged, so they are all the same as tee .
So when you do
tee >(some_command) | some_other_command
Now bash first creates a process to start tee and assigns it stdout half of the channel record, and another process to start some_other_command , and its stdin assigned to read half of the same pipe. He then creates another process to run some_command as described above, assigning it stdin half the read of another channel and leaving it stdout and stderr unchanged. However, stdout already redirected to some_other_command and that some_command inherits.
In your actual example
tee >(sed 's/World/Boy/g'|grep Boy) | grep World
in the end we get:
--> sed 's/World/Boy/g' --> grep Boy -- / \ input --> tee --< \ \ \ ----------------------------------------------> grep World
In one of the questions related to the OP, there is a (not accepted, but correct) answer of F. Hauri , which I adapted here:
echo Hello World | ((tee /dev/fd/5 | grep World >/dev/fd/4) \ 5>&1 | sed 's/World/Boy/' | grep Boy) 4>&1
It takes a little practice to read the basisms like the one above. The important part is that
( commands ) 5>&1
Creates a subshell ( ( ) ) and gives the fd subshell number 5, originally copied from stdout ( 5>&1 ). Inside the subshell /dev/fd/5 refers to this fd. Within a subshell, you can redirect stdout , but this will happen after copying stdout to fd5.
source share