Un bon moyen de faire la différence est de faire quelques essais sur la ligne de commande. Malgré la similarité visuelle dans l'utilisation du <
personnage, il fait quelque chose de très différent d'une redirection ou d'un pipe.
Utilisons la date
commande pour tester.
$ date | cat
Thu Jul 21 12:39:18 EEST 2011
Ceci est un exemple inutile mais il montre que cat
la sortie de date
STDIN a été acceptée et renvoyée. Les mêmes résultats peuvent être obtenus par substitution de processus:
$ cat <(date)
Thu Jul 21 12:40:53 EEST 2011
Cependant, ce qui vient de se passer dans les coulisses était différent. Au lieu de recevoir un flux STDIN, cat
le nom du fichier qu’il devait ouvrir et lire a été transmis. Vous pouvez voir cette étape en utilisant à la echo
place de cat
.
$ echo <(date)
/proc/self/fd/11
Lorsque chat reçoit le nom du fichier, il lit le contenu du fichier pour nous. D'autre part, echo nous a juste montré le nom du fichier qu'il a été transmis. Cette différence devient plus évidente si vous ajoutez plus de substitutions:
$ cat <(date) <(date) <(date)
Thu Jul 21 12:44:45 EEST 2011
Thu Jul 21 12:44:45 EEST 2011
Thu Jul 21 12:44:45 EEST 2011
$ echo <(date) <(date) <(date)
/proc/self/fd/11 /proc/self/fd/12 /proc/self/fd/13
Il est possible de combiner la substitution de processus (qui génère un fichier) et la redirection des entrées (qui connecte un fichier à STDIN):
$ cat < <(date)
Thu Jul 21 12:46:22 EEST 2011
Il semble à peu près la même chose, mais cette fois, le chat a été passé flux STDIN au lieu d'un nom de fichier. Vous pouvez le voir en l'essayant avec echo:
$ echo < <(date)
<blank>
Comme echo ne lit pas STDIN et qu'aucun argument n'a été passé, nous ne recevons rien.
Les pipes et les redirections d'entrée transfèrent le contenu sur le flux STDIN. La substitution de processus exécute les commandes, enregistre leur sortie dans un fichier temporaire spécial, puis transmet ce nom de fichier à la place de la commande. Quelle que soit la commande que vous utilisez la traite comme un nom de fichier. Notez que le fichier créé n'est pas un fichier normal, mais un canal nommé qui est automatiquement supprimé dès qu'il n'est plus nécessaire.
[[ -p <(date) ]] && echo true
. Cela se produittrue
quand je le lance avec bash 4.4 ou 3.2.Je suppose que vous parlez d'
bash
un autre shell avancé, car le shell posix n'a pas de substitution de processus .bash
rapports de page de manuel:En d'autres termes, et d'un point de vue pratique, vous pouvez utiliser une expression comme celle-ci
en tant que nom de fichier pour d'autres commandes nécessitant un fichier en tant que paramètre. Ou vous pouvez utiliser la redirection pour un tel fichier:
Pour revenir à votre question, il me semble que la substitution de processus et les tuyaux n’ont pas grand-chose en commun.
Si vous souhaitez diriger séquentiellement la sortie de plusieurs commandes, vous pouvez utiliser l’un des formulaires suivants:
mais vous pouvez également utiliser la redirection sur la substitution de processus
enfin, si
command3
accepte un paramètre de fichier (en remplacement de stdin)la source
Voici trois choses que vous pouvez faire avec la substitution de processus et qui sont impossibles autrement.
Entrées de processus multiples
Il n'y a simplement aucun moyen de faire cela avec des tuyaux.
Conserver STDIN
Supposons que vous ayez:
Et vous voulez l'exécuter directement. Ce qui suit échoue lamentablement. Bash utilise déjà STDIN pour lire le script, une autre entrée est donc impossible.
Mais cette façon fonctionne parfaitement.
Substitution de processus sortant
Notez également que la substitution de processus fonctionne dans l'autre sens également. Donc, vous pouvez faire quelque chose comme ça:
C’est un exemple un peu compliqué, mais il envoie stdout à
/dev/null
, pendant que nous transmettons stderr à un script sed afin d’extraire les noms des fichiers pour lesquels une erreur "Autorisation refusée" était affichée, puis envoie CES résultats à un fichier.Notez que la première commande et la redirection stdout sont entre parenthèses ( sous-shell ), de sorte que seul le résultat de la commande THAT est envoyé à
/dev/null
et que cela ne gâche pas le reste de la ligne.la source
diff
exemple , vous voudrez peut - être se soucier de cas où lecd
peut échouer:diff <(cd /foo/bar/ && ls) <(cd /foo/baz && ls)
.Si une commande prend une liste de fichiers en tant qu'arguments et traite ces fichiers en entrée (ou en sortie, mais pas couramment), chacun de ces fichiers peut être un pseudo-fichier canal ou / dev / fd nommé, fourni de manière transparente par la substitution de processus:
Cela "acheminera" la sortie des trois commandes à trier, car trier peut prendre une liste de fichiers en entrée sur la ligne de commande.
la source
<()
, à l'instar de nombreuses fonctionnalités avancées du shell, était à l'origine une fonctionnalité ksh et a été adopté par bash et zsh.psub
est spécifiquement une fonctionnalité de poisson, rien à voir avec POSIX.Il convient de noter que la substitution de processus ne se limite pas au formulaire
<(command)
, qui utilise la sortie decommand
sous forme de fichier. Cela peut aussi être sous la forme>(command)
qui alimente un fichier comme entréecommand
. Ceci est également mentionné dans la citation de bash manual dans la réponse de @ enzotib.Pour l'
date | cat
exemple ci-dessus, une commande qui utilise la substitution de processus du formulaire>(command)
pour obtenir le même effet serait,Notez que l'
>
avant>(cat)
est nécessaire. Ceci peut encore être clairement illustré parecho
la réponse de @ Caleb.Donc, sans l’extra
>
, cedate >(cat)
serait la même chose que d’date /dev/fd/63
imprimer un message à stderr.Supposons que vous ayez un programme qui prend uniquement les noms de fichiers en tant que paramètres et ne traite pas
stdin
oustdout
. Je vais utiliser le script trop simplistepsub.sh
pour illustrer cela. Le contenu depsub.sh
estFondamentalement, il teste que ses deux arguments sont des fichiers (pas nécessairement des fichiers normaux) et si c'est le cas, écrivez le premier champ de chaque ligne de
"$1"
à l'"$2"
aide de awk. Ensuite, une commande qui combine tout ce qui est mentionné jusqu'à présent est,Cela va imprimer
et est équivalent à
mais ce qui suit ne fonctionnera pas, et nous devons utiliser la substitution de processus ici,
ou sa forme équivalente
Si
./psub.sh
lit aussi d'stdin
ailleurs ce qui est mentionné ci - dessus, une telle forme équivalente n'existe pas, et dans ce cas il y a rien que nous pouvons utiliser à la place de la substitution de processus (bien sûr vous pouvez également utiliser un fichier de tuyau ou nommé temp, mais c'est une autre récit).la source