¿Hay alguna manera de canalizar la salida de un programa en otros dos programas?

28

Lo siento si esta es una pregunta tonta, pero estoy tratando de lograr algo como esto, pero en una línea:

$ prog1 | prog2
$ prog1 | prog3

Entonces, básicamente quiero ejecutar prog1 y canalizar la salida a prog2 y prog3 por separado (no una tubería encadenada). Al principio, estaba tratando de usar tee pero eso no parecía correcto porque estaba volcando la salida a un archivo (que no es lo que quiero).

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

En algún momento, probablemente me gustaría extender esto a canalizar la salida a más de dos programas, pero estoy comenzando de manera simple por ahora.

$ prog1 | prog2
$ prog1 | prog3
$ prog1 | prog4
...
Longda
fuente
Creo que zsh puede hacer esto.
Keith

Respuestas:

28

Proceso de sustitución.

... | tee >(prog2) | ...
Ignacio Vazquez-Abrams
fuente
1
IIRC que es una extensión bash y no se encuentra en POSIX sh estándar.
Simon Richter
66
@SimonRichter Esta es una extensión ksh93, que también se encuentra en bash y zsh.
Gilles 'SO- deja de ser malvado'
16

Similar a la respuesta de Ignacio, puede usar una tubería temporal con nombre mkfifo(1).

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

Es un poco más detallado, pero funcionaría en sistemas que no tienen sustitución de procesos, como dash. El sleep 1es manejar cualquier condición de carrera.

Arcege
fuente
6

Hay una pequeña placa de utilidad que hace el trabajo:

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

En lugar de escribir en archivos, ptee escribe en todos los fds que se proporcionan en la línea de comando.

ptee es parte de pipexec .

Andreas Florath
fuente
4

No necesita ningún bashism o archivos especiales o nada de eso, no en Linux de todos modos:

% { 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

Destaqué los resultados grepresaltados para mí para mostrar que no solo eran tres resultados de la misma secuencia, sino que también eran el resultado de grepcoincidencias de proceso separadas .

mikeserv
fuente