La substitution de processus est la contre-partie de la substitution de commande. La substitution de commande affecte à une variable le résultat d'une commande, comme dans contenu_rep=`ls -al` ou xref=$( grep mot fichdonnées). La substitution de commande « nourrit » un processus avec la sortie d'un autre processus (en d'autres termes, elle envoie le résultat d'une commande à une autre commande).
Patron de substitution de commande
>(commande)
<(commande)
Ceci lance la substitution de processus. Cette syntaxe utilise les fichiers /dev/fd/<n> pour envoyer le résultat du processus entre parenthèses vers un autre processus. [71]
Il n'y a pas d'espace entre le « < » ou « > » et les parenthèses. Ici, un espace génèrerait un message d'erreur.
bash$ echo >(true) /dev/fd/63 bash$ echo <(true) /dev/fd/63
Bash crée un tube avec deux descripteurs de fichiers, --fIn et fOut--. Le stdin (entrée standard) de true se connecte à fOut (la sortie standard) (dup2(fOut, 0)), puis Bash passe un /dev/fd/fIn comme argument à la commande echo. Sur les systèmes sans fichier /dev/fd/<n>, Bash peut utiliser des fichiers temporaires (merci S.C.).
La substitution de processus peut comparer la sortie de deux commandes différentes, voire même la sortie dûe à différentes options de la même commande.
bash$ comm <(ls -l) <(ls -al) total 12 -rw-rw-r-- 1 bozo bozo 78 Mar 10 12:58 File0 -rw-rw-r-- 1 bozo bozo 42 Mar 10 12:58 File2 -rw-rw-r-- 1 bozo bozo 103 Mar 10 12:58 t2.sh total 20 drwxrwxrwx 2 bozo bozo 4096 Mar 10 18:10 . drwx------ 72 bozo bozo 4096 Mar 10 17:58 .. -rw-rw-r-- 1 bozo bozo 78 Mar 10 12:58 File0 -rw-rw-r-- 1 bozo bozo 42 Mar 10 12:58 File2 -rw-rw-r-- 1 bozo bozo 103 Mar 10 12:58 t2.sh
Utiliser la substitution de processus pour comparer le contenu de deux répertoires (pour connaître les fichiers présents dans l'un mais pas dans l'autre :
diff <(ls $premier_repertoire) <(ls $deuxieme_repertoire)
Quelques autres utilisations de la substitution de processus :
cat <(ls -l) # Même chose que ls -l | cat sort -k 9 <(ls -l /bin) <(ls -l /usr/bin) <(ls -l /usr/X11R6/bin) # Liste tous les fichiers des trois principaux répertoires "bin" et les trie #+ par nom de fichier. # Notez les trois commandes distinctes (Comptez les <) vont "nourrir" 'sort'. diff <(command1) <(command2) # Fournit les différences entre les #+ sorties des commandes. tar cf >(bzip2 -c > file.tar.bz2) $nom_repertoire # Appelle "tar cf /dev/fd/?? $nom_repertoire" et "bzip2 -c > fichier.tar.bz2" # # À cause de la fonctionnalité système /dev/fd/<n>, # le tube entre les deux commandes n'a pas besoin d'être nommé. # # Ceci peut être émulé. # bzip2 -c < pipe > fichier.tar.bz2& tar cf pipe $nom_repertoire rm pipe # ou exec 3>&1 tar cf /dev/fd/4 $nom_repertoire 4>&1 >&3 3>&- | bzip2 -c > fichier.tar.bz2 3>- exec 3>&- # Merci, Stéphane Chazelas
Un lecteur a envoyé cet intéressant exemple de substitution de processus.
# Fragment de script provenant d'une distribution Suse : while read des what mask iface; do # Quelques commandes ... done < <(route -n) # Pour le tester, faisons lui faire quelque chose while read des what mask iface; do echo $des $what $mask $iface done < <(route -n) # Sortie: # Table de routage IP du noyau # Destination Gateway Genmask Flags Metric Ref Use Iface # 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo # Comme Stéphane Chazelas le souligne, voici un équivalent plus aisément compréhensible : route -n | while read des what mask iface; do # Les variables sont affectées par la #+ sortie du tube. echo $des $what $mask $iface done # Ceci engendre la même sortie que ci-dessus. # Néanmoins, comme le précise Ulrich Gayer... #+ cet équivalent simplifié utilise un sous-shell pour la boucle while #+ et donc les variables disparaissent quand l'envoi via le tube se #+ termine. # Néanmoins, Filip Moritz indique qu'il existe une différence subtile #+ entre les deux exemples ci-dessus, comme nous le montre la suite. ( route -n | while read x; do ((y++)); done echo $y # $y n'est toujours pas initialisé while read x; do ((y++)); done < <(route -n) echo $y # $y a le nombre de lignes en sortie de route -n ) # Plus généralement ( : | x=x # semble lancer un sous-shell comme : | ( x=x ) # alors que x=x < <(:) # ne le fait pas ) # C'est utile pour analyser csv ou un fichier de ce genre. # En effet, c'est ce que fait le fragement de code SuSE original.
[71] Ceci a le même effet qu'un tube nommé (fichier temporaire), et, en fait, les tubes nommés étaient autrefois utilisés dans les substitutions de processus.