42 votes

Plusieurs entrées standard ? Comment faire ?

De ce post commandlinefu:

$ 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 programmation Linux---ce n'est pas possible. Je pensais que, par définition, l'entrée standard était un seul flux.

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

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

33voto

Lark Points 1640

Ce n'est pas une entrée standard multiple. Il s'agit d'un bash'ism appelé 'Process Substitution' 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 lire que comme un flux, ce qui signifie qu'elle ne peut pas avancer et reculer avec fseek. Elle doit le lire comme un flux d'octets, comme un tuyau.

Réponse BONUS

Il n'est pas nécessaire de faire beaucoup pour utiliser ceci. Pour votre script, il reçoit un nom de fichier valide en ligne de commande, qui peut être open()é comme n'importe quoi d'autre. Comme d'autres l'ont dit, vous verriez diff /dev/fd/XX /dev/fd/YY. Si vous effectuez un stat() sur l'un de ces pseudo-fichiers, vous verrez que c'est un tube nommé, et vous devez le traiter avec des sémantiques de tuyau - à savoir ne 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 va casser - c'est mis en œuvre comme un tube nommé après tout.

8voto

Dom Points 704

Il y a un stdin et un stdout pour chaque processus. Ils sont généralement connectés au terminal, mais ils peuvent être redirigés séparément l'un de l'autre.

Dans l'exemple, il y a deux processus wget impliqués, chacun ayant son propre stdin et stdout. Chaque processus wget écrit vers -, qui est son stdout. Ensuite, la substitution de processus de bash <(...) connecte le stdout du processus à un pseudo-fichier unique, à partir duquel diff peut lire. Notez que les deux substitutions de processus donnent deux pseudo-fichiers différents! Ainsi, diff voit quelque chose comme :

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

où le stdout de wget -q -O - URL1 est connecté à /dev/fd/XX, et le stdout de wget -q -O - URL2 à /dev/fd/YY.

7voto

<(...) effectue une substitution de processus en bash. La sortie du processus entre parenthèses est envoyée à un descripteur de fichier supplémentaire au-delà des 3 normaux, et un nom de fichier correspondant à ce descripteur de fichier est renvoyé. De cette manière, la sortie d'une commande peut être traitée comme un nom de fichier à transmettre à une autre commande.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X