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.

  1. dans un premier temps (> monfichier) le descripteur de la sortie standard est connecté au fichier monfichier, c'est-à-dire que tout ce qui sort du programme par la sortie standard est dirigé dans ce fichier,
  2. 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 fichier monfichier.

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à.

  1. 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 !
  2. dans un second temps (> monfichier) le descripteur de la sortie standard est connecté au fichier monfichier ... 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 :

  1. un descripteur supplémentaire est créé et connecté au flux de l'erreur standard,
  2. le descripteur de l'erreur standard est connecté au flux de la sortie standard,
  3. le descripteur de la sortie standard est ensuite connecté au flux du descripteur supplémentaire,
  4. 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>&-;