7

I pipe the same content to multiple commands with tee, subshells and redirects like this:

#!/usr/bin/env bash

echo 'hello' | tee \
  >( sleep 3; cat /dev/stdin ) \
  >( sleep 2; cat /dev/stdin ) \
  >( sleep 1; cat /dev/stdin )

wait # Doesn't work :(

However, what I see is that the subshell output is written to the terminal after the main script exits and wait doesn't work:

$ ./test.sh
hello
$ hello
hello
hello

How to properly wait for the subshells?

  • I think this isn't possible. You'd need to capture the PIDs of each subshell, but process substitution will never give them to you. I will be fascinated to see if there is a simple solution though. – Michael Homer Mar 16 '17 at 3:56
  • @MichaelHomer Apparently zsh is wait-ing for the children... – heemayl Mar 16 '17 at 4:07
7

In bash, you can't wait for process substitution. In:

cmd1 > >(cmd2)

the whole command finish as soon as cmd1 finish, regardless the status of cmd2.

You have to implement a mechanism to signal the parent process that the cmd2 have finished. An easy way, using a fifo:

#!/usr/bin/env bash

trap 'rm wait.fifo' EXIT
mkfifo wait.fifo

echo 'hello' | tee \
  >( sleep 3; cat /dev/stdin; : >wait.fifo ) \
  >( sleep 2; cat /dev/stdin; : >wait.fifo ) \
  >( sleep 1; cat /dev/stdin; : >wait.fifo )

for (( i=0;i<3;i++ )); do read <wait.fifo; done
  • Works indeed, thanks! Although I ended up writing to a file and starting the commands separately. – serega Mar 16 '17 at 14:15

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.