Existe-t-il un moyen de diriger la sortie d'un programme vers deux autres programmes?

28

Désolé si c'est une question idiote mais j'essaie d'accomplir quelque chose comme ça mais sur une seule ligne:

$ prog1 | prog2
$ prog1 | prog3

Donc, je veux essentiellement exécuter prog1 et diriger la sortie vers prog2 et prog3 séparément (pas un canal chaîné). Au début, j'essayais d'utiliser tee, mais cela ne me semblait pas correct car il vidait la sortie dans un fichier (ce qui n'est pas ce que je veux).

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

À un moment donné, je voudrais probablement étendre cela à la canalisation de la sortie vers plus de deux programmes, mais je commence simplement pour l'instant.

$ prog1 | prog2
$ prog1 | prog3
$ prog1 | prog4
...
longda
la source
Je pense que zsh peut le faire.
Keith

Réponses:

28

Substitution de processus.

... | tee >(prog2) | ...
Ignacio Vazquez-Abrams
la source
1
IIRC qui est une extension bash et introuvable dans le POSIX sh standard.
Simon Richter
6
@SimonRichter Il s'agit d'une extension ksh93, également trouvée dans bash et zsh.
Gilles 'SO- arrête d'être méchant'
16

Semblable à la réponse d'Ignacio, vous pouvez utiliser un canal nommé temporaire à l'aide de mkfifo(1).

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

C'est un peu plus détaillé, mais cela fonctionnerait sur des systèmes qui n'ont pas de substitution de processus, comme dash. Il sleep 1s'agit de gérer toutes les conditions de course.

Arcege
la source
6

Il y a un petit utilitaire PTEE qui fait le travail:

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

Au lieu d'écrire dans des fichiers, ptee écrit dans tous les fds indiqués sur la ligne de commande.

ptee fait partie de pipexec .

Andreas Florath
la source
4

Vous n'avez pas besoin de bashismes ou de fichiers spéciaux ou de tout cela - pas sous Linux de toute façon:

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

J'ai mis en vedette les résultats grepmis en évidence pour moi pour montrer qu'ils n'étaient pas seulement trois résultats du même flux, mais ils étaient également le résultat de grepcorrespondances de processus distinctes .

mikeserv
la source