33

Sorry if this is a silly question but I'm trying to accomplish something like this but on one line:

$ prog1 | prog2
$ prog1 | prog3

So, I basically want to execute prog1 and pipe the output to prog2 and prog3 separately (not a chained pipe). At first, I was trying to use tee but that didn't seem right because it was dumping output to a file (which is not what I want).

$ prog1 | tee prog2 | prog3 # doesn't work - creates file "prog2"

At some point, I'd probably want to extend this to piping the output to more than two programs but I'm just starting simple for now.

$ prog1 | prog2
$ prog1 | prog3
$ prog1 | prog4
...
longda
  • 431

4 Answers4

32

Process substitution.

... | tee >(prog2) | ...
17

Similar to Ignacio's answer, you could use a temporary named pipe using mkfifo(1).

mkfifo /tmp/teedoff.$$; cmd | tee /tmp/teedoff.$$ | prog2 & sleep 1; prog3 < /tmp/teedoff.$$; rm /tmp/teedoff.$$

It's a bit more verbose, but it would work on systems that do not have process substitution, like dash. The sleep 1 is to handle any race conditions.

Arcege
  • 22,536
8

There is a small utility ptee which does the job:

prog1 | ptee 2 3 4 2> >(prog2) 3> >(prog3) 4> >(prog4)

Instead of writing to files, ptee writes to all fds which are given on the command line.

ptee is part of pipexec.

5

You don't need any bashisms or special files or any of that - not in Linux anyway:

% { prog1 | tee /dev/fd/3 | prog2 >&2 ; } 3>&1 | prog3 

{ { printf %s\\t%s\\t%s\\n \
    "this uneven argument list" \
    "will wrap around" to \
    "different combinations" \
    "for each line." "Ill pick out" \
    "a few words" "and grep for them from" \
    "the same stream." | 
 tee /dev/fd/3 /dev/fd/4 | 
 grep combination >&2 ; } 3>&1 |
 grep pick >&2 ; } 4>&1 | 
 grep line

different combinations  for each *line.*  Ill pick out
different combinations  for each line.  Ill *pick* out
different *combinations*  for each line.  Ill pick out

I starred the results grep highlighted for me to show they were not only three results from the same stream, but they were also the result of separate grep process matches.

mikeserv
  • 58,310