Bash
Substitution de processus
Recherche…
Remarques
La substitution de processus est une forme de redirection dans laquelle l'entrée ou la sortie d'un processus (une séquence de commandes) apparaît sous la forme d'un fichier temporaire.
Comparer deux fichiers du Web
Ce qui suit compare deux fichiers avec diff
utilisant la substitution de processus au lieu de créer des fichiers temporaires.
diff <(curl http://www.example.com/page1) <(curl http://www.example.com/page2)
Alimenter une boucle while avec la sortie d'une commande
Cela alimente un while
en boucle avec la sortie d'un grep
commande:
while IFS=":" read -r user _
do
# "$user" holds the username in /etc/passwd
done < <(grep "hello" /etc/passwd)
Avec la commande coller
# Process substitution with paste command is common
# To compare the contents of two directories
paste <( ls /path/to/directory1 ) <( ls /path/to/directory1 )
Fichiers concaténés
Il est bien connu que vous ne pouvez pas utiliser le même fichier pour l'entrée et la sortie dans la même commande. Par exemple,
$ cat header.txt body.txt >body.txt
ne fait pas ce que vous voulez Au moment où cat
lit body.txt
, il a déjà été tronqué par la redirection et il est vide. Le résultat final sera que body.txt
contiendra body.txt
le contenu de header.txt
.
On pourrait penser à éviter cela avec la substitution de processus, c’est-à-dire que la commande
$ cat header.txt <(cat body.txt) > body.txt
forcera le contenu original de body.txt
à être sauvegardé dans un tampon quelque part avant que le fichier ne soit tronqué par la redirection. Ça ne marche pas Le cat
entre parenthèses commence à lire le fichier uniquement après que tous les descripteurs de fichiers ont été configurés, tout comme celui externe. Il est inutile d'essayer d'utiliser la substitution de processus dans ce cas.
La seule façon d'ajouter un fichier à un autre fichier consiste à créer un fichier intermédiaire:
$ cat header.txt body.txt >body.txt.new
$ mv body.txt.new body.txt
c'est ce que font les programmes sed
ou perl
ou similaires sous le tapis lorsqu'ils sont appelés avec une option edit-in-place (généralement -i
).
Diffuser un fichier via plusieurs programmes à la fois
Cela compte le nombre de lignes dans un gros fichier avec wc -l
tout en le compressant simultanément avec gzip
. Les deux fonctionnent en même temps.
tee >(wc -l >&2) < bigfile | gzip > bigfile.gz
Normalement, tee
écrit son entrée dans un ou plusieurs fichiers (et stdout). Nous pouvons écrire dans les commandes au lieu des fichiers avec tee >(command)
.
Ici, la commande wc -l >&2
compte les lignes lues depuis le tee
(qui à son tour lit depuis le bigfile
). (Le nombre de lignes est envoyé à stderr ( >&2
) pour éviter de mélanger avec l'entrée de gzip
.) La sortie standard de tee
est transmise simultanément à gzip
.
Pour éviter l'utilisation d'un sous-shell
Un aspect majeur de la substitution de processus est qu’il nous permet d’éviter l’utilisation d’un sous-shell lorsqu’il commande des commandes depuis le shell.
Cela peut être démontré par un exemple simple ci-dessous. J'ai les fichiers suivants dans mon dossier actuel:
$ find . -maxdepth 1 -type f -print
foo bar zoo foobar foozoo barzoo
Si je conduis vers une boucle while
/ read
qui incrémente un compteur comme suit:
count=0
find . -maxdepth 1 -type f -print | while IFS= read -r _; do
((count++))
done
$count
maintenant ne contient pas 6
, car il a été modifié dans le contexte du sous-shell. Toutes les commandes présentées ci-dessous sont exécutées dans un contexte de sous-shell et la portée des variables utilisées est perdue après la fin du sous-shell.
command &
command | command
( command )
La substitution de processus résoudra le problème en évitant d'utiliser le tuyau |
opérateur comme dans
count=0
while IFS= read -r _; do
((count++))
done < <(find . -maxdepth 1 -type f -print)
Cela conservera la valeur de la variable count
car aucun sous-shell n'est invoqué.