Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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
...
share|improve this question
    
I think zsh can do this. –  Keith Jun 8 '12 at 11:30

4 Answers 4

Process substitution.

... | tee >(prog2) | ...
share|improve this answer
1  
IIRC that is a bash extension and not found in standard POSIX sh. –  Simon Richter Jun 8 '12 at 7:01
3  
@SimonRichter This is a ksh93 extension, also found in bash and zsh. –  Gilles Jun 8 '12 at 23:45

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.

share|improve this answer

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.

share|improve this answer

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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