bash version 4 has coproc command that allows this done in pure bash without named pipes:
coproc cmd1 eval "exec cmd2 <&${COPROC[0]} >&${COPROC[1]}" Some other shells also can do coproc as well.
Below is more detailed answer but chains three commands, rather than two, which makes a only a little more interesting.
If you are happy to also use cat and stdbuf then construct can be made easier to understand.
Version using bash with cat and stdbuf, easy to understand:
# start pipeline coproc { cmd1 | cmd2 | cmd3 } # create command to reconnect STDOUT `cmd3` to STDIN of `cmd1` endcmd="exec stdbuf -i0 -o0 /bin/cat <&${COPROC[0]} >&${COPROC[1]}" # eval the command. eval "${endcmd}" Note, have to use eval because variable expansion in <&$var is illegal in my versio of bash 4.2.25.
Version using pure bash: Break up into two parts, launch first pipeline under coproc, then lunch second part, (either a single command or a pipeline) reconnecting it to the first:
coproc { cmd 1 | cmd2 } endcmd="exec cmd3 <&${COPROC[0]} >&${COPROC[1]}" eval "${endcmd}" Proof of concept:
file ./prog, just a dummy prog to consume, tag and re-print lines. Using subshells to avoid buffering problems maybe overkill, it's not the point here.
#!/bin/bash let c=0 sleep 2 [ "$1" == "1" ] && ( echo start ) while : ; do line=$( head -1 ) echo "$1:${c} ${line}" 1>&2 sleep 2 ( echo "$1:${c} ${line}" ) let c++ [ $c -eq 3 ] && exit done file ./start_cat This is a version using bash, cat and stdbuf
#!/bin/bash echo starting first cmd>&2 coproc { stdbuf -i0 -o0 ./prog 1 \ | stdbuf -i0 -o0 ./prog 2 \ | stdbuf -i0 -o0 ./prog 3 } echo "Delaying remainer" 1>&2 sleep 5 cmd="exec stdbuf -i0 -o0 /bin/cat <&${COPROC[0]} >&${COPROC[1]}" echo "Running: ${cmd}" >&2 eval "${cmd}" or file ./start_part. This is a version using pure bash only. For demo purposes I am still using stdbuf because your real prog would have to deal with buffering internally anyway to avoid blocking due to buffering.
#!/bin/bash echo starting first cmd>&2 coproc { stdbuf -i0 -o0 ./prog 1 \ | stdbuf -i0 -o0 ./prog 2 } echo "Delaying remainer" 1>&2 sleep 5 cmd="exec stdbuf -i0 -o0 ./prog 3 <&${COPROC[0]} >&${COPROC[1]}" echo "Running: ${cmd}" >&2 eval "${cmd}" Output:
> ~/iolooptest$ ./start_part starting first cmd Delaying remainer 2:0 start Running: exec stdbuf -i0 -o0 ./prog 3 <&63 >&60 3:0 2:0 start 1:0 3:0 2:0 start 2:1 1:0 3:0 2:0 start 3:1 2:1 1:0 3:0 2:0 start 1:1 3:1 2:1 1:0 3:0 2:0 start 2:2 1:1 3:1 2:1 1:0 3:0 2:0 start 3:2 2:2 1:1 3:1 2:1 1:0 3:0 2:0 start 1:2 3:2 2:2 1:1 3:1 2:1 1:0 3:0 2:0 start That does it.