3

This question already has an answer here:

When we run this with a POSIX shell,

$ cmd0 | cmd1

STDOUT of cmd0 is piped to STDIN of cmd1.

Q: On top of this, how can I also pipe STDOUT of cmd1 to STDIN of cmd0?

Is it mandatory to use redirect from/into a named pipe (FIFO) ? I don't like named pipes very much because they occupy some filesystem paths and I need to worry about name collisions. Or do I have to call pipe(2) via C, Python or some general purpose programming languages?

(Both cmd0 and cmd1 do some network I/O, so they won't block each other forever.)

marked as duplicate by Stephen Harris, jsbillings, Jeff Schaller, Networker, slm Jul 17 '16 at 13:26

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • Good to know some *nixes have "bidirectional pipes"... I wasn't imaginative enough to search across the archive with such a term. – nodakai Jul 18 '16 at 5:19
13

On systems with bi-directional pipes (not Linux), you can do:

cmd0 <&1 | cmd1 >&0

On Linux, you can do:

{ cmd0 < /dev/fd/3 | cmd1 3>&-; } 3>&1 | :

That works because on Linux (and Linux only) /dev/fd/x where x is a fd to a pipe (named or not) acts like a named pipe, that is, opening it in read mode gets you the reading end and in write mode gets you the writing end.

With the yash shell and its x>>|y pipeline redirection operator:

{ cmd0 <&4 3<&- 4<&- | cmd1 >&3 3>&- 4>&-; } 3>>|4

With shells with coproc support:

  • zsh:

     coproc cmd0
     cmd1 <&p >&p
    
  • ksh

     cmd0 |&
     cmd1 <&p >&p
    
  • bash4+

     coproc cmd0
     cmd1 <&"${COPROC[0]}" >&"${COPROC[1]}"
    

Some dedicated tool based approaches (shamelessly copied from answers on this very similar question):

pipexec [ A /path/to/cmd0 ] \
        [ B /path/to/cmd1 ] \
        '{A:1>B:0}' '{A:0>B:1}'

Or:

dpipe cmd0 = cmd1

Or:

socat EXEC:cmd0 EXEC:cmd1,nofork # using socketpairs
socat EXEC:cmd0,commtype=pipes EXEC:cmd1,nofork # using pipes

I don't know about python, but that's also relatively easily done in perl:

perl -e 'pipe STDOUT,STDIN; exec "cmd0 | cmd1"'

In any case, beware of deadlocks!

Not the answer you're looking for? Browse other questions tagged or ask your own question.