Un bon tuyau
Par Patrice Pillot, jeudi 23 octobre 2008 à 11:45 :: Informatique :: #29 :: rss
_AleX_ a titillé son monde l'autre jour sur #toulibre en demandant ce que fait le bout de code suivant : 3>&2 2>&1 1>&3 3>&-;. Ceci m'a permis d'enfin mettre mes idées au clair sur la question des redirections (c'était pas trop tôt pourrait-on dire...).
Pour décoder la colle d'_AleX_, il faut être au clair sur la signification des redirections. On parle toujours au sujet de ces symboles de redirection des entrées et sorties (« ... la sortie est redirigée sur le fichier machin-chose ... »). Pour être plus précis on devrait parler de connexion des entrées/sorties. En effet, on sait que chaque programme a par défaut trois descripteurs internes : l'entrée standard, la sortie standard et l'erreur standard. Par défaut, toujours, lors d'une invocation depuis un terminal, ces trois descripteurs sont connectés au terminal. Ce que permettent les symboles dits de redirection, c'est de connecter ces descripteurs à autre chose, par exemple un fichier. Rediriger la sortie standard vers un fichier revient donc à connecter le descripteur associé à un nouveau flux, par exemple un fichier.
Mettons ceci en pratique en prenant l'exemple assez fréquent qui consiste à rediriger (j'emploie à dessein ce terme flou) l'erreur standard et la sortie standard dans un même et unique fichier. Ceci se fait ordinairement par l'écriture suivante :
$ macommande > monfichier 2>&1
L'écriture qui suit est par contre fautive :
$ macommande 2>&1 > monfichier
Pourtant, dans un cas comme dans l'autre, l'erreur standard semble bien redirigée vers la sortie standard et celle-ci vers le fichier...
Oublions donc ce terme de redirection et employons, comme suggéré plus haut, le terme de connexion pour examiner ce qui se passe dans le premier exemple. Je rappelle que les éléments de la ligne de commande sont évalués de gauche à droite.
- dans un premier temps (
> monfichier) le descripteur de la sortie standard est connecté au fichiermonfichier, c'est-à-dire que tout ce qui sort du programme par la sortie standard est dirigé dans ce fichier, - dans un deuxième temps (
2>&1) le descripteur de l'erreur standard est connectée au même flux auquel est connnectée la sortie standard, c'est-à-dire ici au fichiermonfichier.
Dans ce premier exemple, les données transmises à l'erreur standard et à la sortie standard sont donc bien, in fine, écrites dans le fichier monfichier.
Examinons de la même façon le deuxième exemple, fautif celui-là.
- dans un premier temps (
2>&1) le descripteur de l'erreur standard est connecté au flux auquel est elle-même connectée la sortie standard ... c'est-à-dire au terminal puisque par défaut aussi bien la sortie standard que l'erreur standard sont connectées au terminal ! Cette écriture ne change donc rien ! - dans un second temps (
> monfichier) le descripteur de la sortie standard est connecté au fichiermonfichier... mais le descripteur de l'erreur standard reste lui connecté au terminal !
Maintenant que tout celà est au clair, l'exemple d'_AleX_ devient limpide :
- un descripteur supplémentaire est créé et connecté au flux de l'erreur standard,
- le descripteur de l'erreur standard est connecté au flux de la sortie standard,
- le descripteur de la sortie standard est ensuite connecté au flux du descripteur supplémentaire,
- enfin, le descripteur supplémentaire est fermé.
Cette opération permet donc d'échanger les flux associés à la sortie et à l'erreur standard au moyen d'un descripteur temporaire. Ceci peut sembler inutile puisque dans le cas général la sortie et l'erreur standard sont toutes les deux associées au terminal, mais d'une part il ne faut pas oublier que le programme invoqué peut modifier ceci en interne et associer ces descripteurs à des flux particuliers, et d'autre part que ce mécanisme n'est pas exclusif d'autres redirections, comme par exemple :
$ macommande > fichier_sortie 2> fichier_erreur 3>&2 2>&1 1>&3 3>&-;
Commentaires
Aucun commentaire pour le moment.
Ajouter un commentaire
Les commentaires pour ce billet sont fermés.