Discussion:
[Help-bash] What the process started by <() may not be a child?
Peng Yu
2018-11-15 15:04:14 UTC
Permalink
Hi,

I don't understand the difference between the two <(). Why the first
one is not a child but the second one is a child? Where is this
documented? If I do want to wait for both to be finished, is there a
way to do so in bash? Thanks.

$ cat ./main.sh
#!/usr/bin/env bash
# vim: set noexpandtab tabstop=2:

echo <(echo 1:$BASHPID>&2) <(echo 2:$BASHPID>&2)
echo "$!"
wait "$(($!-1))"

$ ./main.sh
1:38520
/dev/fd/63 /dev/fd/62
38521
2:38521
./main.sh: line 6: wait: pid 38520 is not a child of this shell
--
Regards,
Peng
Greg Wooledge
2018-11-15 15:10:37 UTC
Permalink
Post by Peng Yu
I don't understand the difference between the two <(). Why the first
one is not a child but the second one is a child?
echo <(echo 1:$BASHPID>&2) <(echo 2:$BASHPID>&2)
echo "$!"
They're both background child processes. The problem is that there is
only one $! parameter available, and it can only hold one PID at at time.
Post by Peng Yu
If I do want to wait for both to be finished, is there a
way to do so in bash? Thanks.
At some point you have to give up on the sugary syntactic additions
and just write some actual code. In this case, acknowledge that <() is
syntactic sugar for setting up your own named pipe and background
process, and that you might have exceeded its usefulness.

fifo=something
trap 'rm -f "$fifo"' EXIT
mkfifo "$fifo" || exit
writer process 1 > "$fifo" & pid1=$!
cat "$fifo" <(writer process 2)
pid2=$!
wait "$pid1" "$pid2"
Russell Lewis
2018-11-15 17:53:51 UTC
Permalink
My trick for waiting for multiple process-substitution is to append a cat
command to the end of the line. It suspect that it doesn't work for all
possible combinations of commands, and it also adds to overhead (since all
I/O is copied through another process), but for many of the simple tasks I
do, it works well:
echo <(cmd1) <(cmd2) | cat

Russ
Post by Peng Yu
Hi,
I don't understand the difference between the two <(). Why the first
one is not a child but the second one is a child? Where is this
documented? If I do want to wait for both to be finished, is there a
way to do so in bash? Thanks.
$ cat ./main.sh
#!/usr/bin/env bash
echo <(echo 1:$BASHPID>&2) <(echo 2:$BASHPID>&2)
echo "$!"
wait "$(($!-1))"
$ ./main.sh
1:38520
/dev/fd/63 /dev/fd/62
38521
2:38521
./main.sh: line 6: wait: pid 38520 is not a child of this shell
--
Regards,
Peng
Loading...