Entrée standard multiple? Comment?

36

De ce poste en ligne de commande :

$ diff <(wget -q -O - URL1) <(wget -q -O - URL2)

On dirait plusieurs entrées standard mais --- si je me souviens bien de mon cours de Linux Porgramming --- ça ne peut pas être ça. Je pensais que, par définition, l'entrée standard était un flux.

Peut-être que cela a à voir avec stdin? Quelqu'un peut m'expliquer cela; peut-être fournir des liens vers la documentation.

Bonus: comment un script gérerait-il ces multiples flux? Si quelqu'un pouvait fournir un exemple Python ou Perl, ce serait très utile.

Belmin Fernandez
la source
1
Bonne question. Si vous n'êtes pas au courant, il existe un site de questions / réponses unix / linux: unix.stackexchange.com
Matt Ellen
2
Documentation pour les substitutions de processus: gnu.org/software/bash/manual/bashref.html#Process-Substitution
glenn jackman
Remarque: dans Bash, c'est <(…); dans la syntaxe de substitution de processus Zsh est =(…).
Kamil Maciorowski

Réponses:

27

Ce n'est pas une entrée standard multiple. Il s'agit d'un bashisme qui a appelé «Substitution de processus» http://tldp.org/LDP/abs/html/process-sub.html

Il crée un pseudo fichier ( /dev/fd/something) pour chaque substitution. C'est assez utile. La commande ne peut être lue que comme un flux, ce qui signifie qu'elle ne peut pas aller et venir avec fseek. Il doit le lire comme un flux d'octets, comme un tuyau.

BONUS Answer

Vous n'avez pas besoin d'en faire trop pour l'utiliser. En ce qui concerne votre script, il obtient un nom de fichier valide sur la ligne de commande, qui peut être ouvert () comme n'importe quoi d'autre. Comme d'autres l'ont dit, vous verriez diff /dev/fd/XX /dev/fd/YY. Si vous faites une stat () sur l'un de ces pseudo-fichiers, vous verrez qu'il s'agit d'un canal nommé, et vous devez le traiter avec la sémantique du tube - à savoir pas fseek () ou ftell (). Si vous faites un test stat () pour voir explicitement s'il s'agit d'un fichier (par exemple [ -f $1 ]), cela se cassera - cela est implémenté comme un canal nommé après tout.

Rich Homolka
la source
Une autre bonne référence pour la substitution de processus bash - wiki.bash-hackers.org/syntax/expansion/proc_subst
studgeek
Et quelle est l'utilisation recommandée de cette fonctionnalité? Soutenez-le chaque fois que votre programme pourrait raisonnablement fonctionner avec un flux au lieu d'exiger un fichier avec un accès aléatoire?
masterxilo
7

<(...)traite la substitution dans bash. La sortie du processus dans les parens est envoyée à un descripteur de fichier supplémentaire au-delà de la normale 3, et un nom de fichier est retourné correspondant à ce descripteur de fichier. De cette façon, la sortie d'une commande peut être traitée comme un nom de fichier à passer à une autre commande.

Ignacio Vazquez-Abrams
la source
7

Il y en a un stdinet un stdout pour chaque processus . Ils sont généralement connectés au terminal, mais ils peuvent être redirigés séparément les uns des autres.

Dans l'exemple, il y a deux wgetprocessus impliqués, chacun ayant son propre stdinet stdout. Chaque wgetprocessus écrit -, ce qui est le sien stdout. Ensuite, bashla substitution de processus <(...)relie le stdoutprocessus à un pseudo-fichier unique, à partir duquel diffpeut être lu. Notez que les deux substitutions de processus produisent deux pseudo-fichiers différents! Ainsi, diffvoit quelque chose comme:

diff /dev/fd/XX /dev/fd/YY

où le stdoutde wget -q -O - URL1est connecté à /dev/fd/XX, et le stdoutde wget -q -O - URL2à /dev/fd/YY.

musiphil
la source