Split an input for different command and combine the result
When you tee to multiple process substitutions, you're not guaranteed to get the output in any particular order, so you'd better stick with
paste -t',' <(commanda < file) <(commandb < file)
Assuming cat myfile
stands for some expensive pipeline, I think you'll have to store the output, either in a file or a variable:
output=$( some expensive pipeline )
paste -t',' <(commanda <<< "$output") <(commandb <<< "$output")
Using your example:
output=$( seq 4 )
paste -d' ' <(cat <<<"$output") <(tac <<<"$output") <(awk '$1*=2' <<<"$output")
1 4 2
2 3 4
3 2 6
4 1 8
Another thought: FIFOs, and a single pipeline
mkfifo resulta resultb
seq 4 | tee >(tac > resulta) >(awk '$1*=2' > resultb) | paste -d ' ' - resulta resultb
rm resulta resultb
1 4 2
2 3 4
3 2 6
4 1 8
The yash
shell has unique features (pipeline redirection and process redirection) that make that easier there:
cat myfile | (
exec 3>>|4
tee /dev/fd/5 5>(commanda >&3 3>&-) 3>&- |
commandb 3>&- |
paste -d , /dev/fd/4 - 3>&-
)
3>>|4
(pipeline redirection) creates a pipe where the writing end is on fd 3 and the reading end on fd 4.
3>(commanda>&3)
is process redirection, a bit like ksh/zsh/bash process substitution but just does the redirection and doesn't substitute with the /dev/fd/n
. ksh
's >(cmd)
is more or less the same as yash
's n>(cmd) /dev/fd/n
(there n
is a file descriptor chosen by ksh
on which you have no control).
With zsh
:
pee() (
n=0 close_in= close_out= inputs=() outputs=()
merge_command=$1; shift
for cmd do
eval "coproc $cmd $close_in $close_out"
exec {i}<&p {o}>&p
inputs+=($i) outputs+=($o)
eval i$n=$i o$n=$o
close_in+=" {i$n}<&-" close_out+=" {o$n}>&-"
((n++))
done
coproc :
read -p
eval tee /dev/fd/$^outputs $close_in "> /dev/null &
" exec $merge_command /dev/fd/$^inputs $close_out
)
Then use as:
$ echo abcd | pee 'paste -d,' 'tr a A' 'tr b B' 'tr c C'
Abcd,aBcd,abCd
That's adapted from this other question where you'll find some detailed explanations and hints at the limitations (beware of deadlocks!).