I would like to send stdout to multiple commands, however I'm not sure how do I read from standard input within process substitution?
My attempts:
$ echo foo >(cat /dev/stdin) >(cat /dev/stdin)
foo /dev/fd/63 /dev/fd/62
$ echo foo >(cat -) >(cat -)
foo /dev/fd/63 /dev/fd/62
$ echo foo >(cat <&3) >(cat <&3) 3<&0
foo /dev/fd/63 /dev/fd/62
-bash: 3: Bad file descriptor
-bash: 3: Bad file descriptor
Alternative version of the same problem:
$ cat file | tee &>/dev/null >(cmd1 /dev/stdin) >(cmd2 /dev/stdin)
What's the right way of doing this?
1 Answer 1
This reads from stdin:
echo foo | tee >(read line </dev/stdin; echo "internal $line")
You have to keep in mind that a process substitution acts "like" a file.
It could be used where a file is expected. The command tee expects to write to a file.
In that command we are being specific about the device to read from with: /dev/stdin. In that simple example, the /dev/stdin could be removed and that will work also:
echo foo | tee >(read line; echo "internal $line")
If I am understanding your need correctly, this will work:
$ echo foo | tee >(read a </dev/stdin; echo "a is $a") \
>(read b </dev/stdin; echo "b is $b") \
>(read c </dev/stdin; echo "c is $c")
foo
a is foo
c is foo
b is foo
I omitted the PS2 prompt to reduce confusion. Note that each Process Substitution replaces the use of a file (as: tee FILE FILE ....
).
The read does not have to be the first command.
$ echo foo > >(echo "hello" | read b; read a </dev/stdin; echo "a is $a")
a is foo
Note that here the "Process Substitution" needs a redirection,
that is the reason of the two > >(
idiom.
A simple echo, will only print the number of the fd used (the name of the file):
$ echo >(echo "hello")
/dev/fd/63
hello
It is similar to:
$ echo "$file"
filename
Whereas this is a very different idiom:
$ echo > "$file"
Explore related questions
See similar questions with these tags.
-
points to stdin.<(cat)
, and I am looking for:>(cat -)
.echo foo | tee >(cat) >(cat)
?