Capsule de théorie Redirection des entrées-sorties standard

Introduction

Dans les systèmes d’exploitation de type Unix ainsi que dans d’autres systèmes qui s’en sont inspirés (notamment ceux de Microsoft), un programme communique avec le terminal à travers des entrées-sorties qui lui sont présentées comme des fichiers à accès séquentiel. Chacun de ces fichiers est identifié par un numéro : 0 pour l’entrée standard (stdin), 1 pour la sortie standard (stdout), et 2 pour la sortie d’erreur standard (stderr).

Par défaut, lorsqu’on lance un programme depuis la ligne de commande, celui-ci reçoit les mêmes entrées-sorties que le shell. Ainsi, lorsqu’un programme lit des caractères sur l’entrée standard, ceux-ci proviennent en principe du terminal où ils ont été saisis au clavier, et lorsqu’il écrit des caractères dans la sortie standard ou dans la sortie d’erreur, ceux-ci sont envoyés au terminal qui effectue l’opération correspondant à chacun d’eux (imprimer le caractère, revenir à la ligne, actionner la cloche, positionner le curseur, changer la couleur, etc.). Mais le shell permet également de rediriger ces entrées-sorties vers d’autres fichiers et c’est ce que nous allons voir dans les lignes qui suivent.

Entrée standard, sortie standard et erreur standard

Lorsqu’un programme est lancé depuis la ligne de commande du shell, il reçoit les mêmes entrées-sorties que le shell. Celles-ci sont en principe liées au clavier et à l’écran du terminal comme l’illustre la figure 1.

commande cat avec redirection de l’entrée standard
Fig. 1 – Entrée/sortie par défaut

Le programme cat écrit dans la sortie standard les caractères qu’il reçoit de l’entrée standard. Si on lance ce programme sans autres arguments, on constate qu’il répète chaque ligne que vous saisissez, jusqu’à ce qu’il trouve un caractère EOF (fin de fichier) qu’on peut envoyer avec la combinaison de touches ctrl-D (^D) ou que vous l’interrompiez avec ^C.

1
2
3
4
5
6
dev@vmdev:~ cat
une ligne de texte
une ligne de texte
une autre ligne de texte
une autre ligne de texte
^D
Fig. 2 – cat

On remarque que cat ne répète pas chaque caractère, mais chaque ligne. Ce comportement n’est pas dû au programme, mais au terminal. En effet, si l’on ne précise rien, celui-ci accumule les caractères dans une mémoire tampon (buffer) et n’envoie les caractères que lorsque la touche Return est pressée. Ce mode de fonctionnement, appelé « cooked mode » par opposition à « raw mode », vous permet de corriger d’éventuelles fautes de frappe sur une ligne de texte avant de l’envoyer.

Redirections de la sortie standard.

Vous vous doutez certainement qu’il ne sert à rien de lancer la commande cat comme nous venons de le faire. En revanche, en redirigeant la sortie standard avec l’opérateur de redirection >, la commande cat nous permet de saisir le contenu d’un fichier.

1
2
3
4
5
dev@vmdev:~ cat > data.txt
ligne 1
ligne 2
ligne 3
^D
Fig. 3 – Redirection de la sortie de la commande cat

Schématiquement, la situation est la suivante :

Redirection de la sortie standard
Fig. 4 – Redirection de la sortie standard

Lors de la redirection de la sortie standard à l’aide de l’opérateur > vers un fichier déjà existant, les nouvelles données remplacent les données qu’il contient. Pour ajouter les nouvelles données à la suite des données existantes, on peut utiliser l’opérateur >>.

Redirections de la sortie standard.

Si on redirige maintenant l’entrée standard avec l’opérateur de redirection <, les données que reçoit le programme ne proviennent plus du clavier, mais d’un fichier comme le montre l’illustration de la figure 5.

Redirection de l’entrée et de la sortie standard
Fig. 5 – Redirection de l’entrée et de la sortie standard

Pour autant que la norme d’encodage du fichier corresponde à celle du terminal, en redirigeant l’entrée standard de la commande cat on peut l’utiliser pour afficher le contenu d’un fichier. La commande ci-dessous à pour effet d’afficher le contenu du fichier data.txt.

1
dev@vmdev:~ cat < data.txt

PowerShell ne permet pas ce type de redirection. Pour passer le contenu d’un fichier à une commande, on peut lui passer le résultat de Get-Content à travers un tube (voir la section 6).

Redirections de la sortie et de l’entrée standard

Il est également possible d’utiliser les deux opérateurs redirection < et > dans une même commande, pour rediriger à la fois l’entrée et la sortie standard. Par exemple, en redirigeant l’entrée et la sortie de cat, on copie le fichier d’entrée dans le fichier de sortie.

Redirection de la sortie et de l’entrée standard
Fig. 6 – Redirection de la sortie et de l’entrée standard

L’utilisation de l’opérateur >> avec cat permet de concaténer le contenu de plusieurs fichiers.

Redirection de la sortie d’erreur

Lorsqu’une erreur survient, l’usage veut que le programme informe l’utilisateur en écrivant un message dans la sortie d’erreur standard. En principe, les caractères envoyés vers cette sortie sont envoyés vers le terminal, mais il possible de les rediriger vers un fichier. Pour cela, on utilise l’opérateur 2>. Il s’agit en fait du même opérateur que pour la redirection de la sortie standard auquel on adjoint le numéro du fichier correspondant à la sortie à rediriger. Pour rediriger la sortie standard, on peut également utiliser l’opérateur 1>.

Redirection de la sortie d’erreur
Fig. 7 – Redirection de la sortie d’erreur

Redirections de la sortie standard d’une commande vers la sortie d’erreur

Puisque la sortie standard et la sortie d’erreur standard sont des fichiers, on peut également rediriger l’une dans l’autre. Pour cela on utilise les opérateurs 2> ou 1> et au lieu de spécifier le nom d’un fichier on spécifie le numéro d’une sortie précédé d’un « et » commercial (&). Par exemple, pour rediriger la sortie de standard de la commande echo dans la sortie d’erreur, on écrira la commande suivante :

1
dev@vmdev:~ echo "message d’erreur" 1>&2

On peut utiliser ce type de redirection pour écrire un message d’erreur dans un script bash ou fichier de commande Windows. En PowerShell, ce type de redirection n’est pas possible, mais la commande Write-Error permet d’écrire explicitement dans la sortie d’erreur.

Redirection de la sortie standard d’une commande vers la sortie d’erreur
Fig. 8 – Redirection de la sortie standard d’une commande vers la sortie d’erreur

Enchainement de commandes avec des tubes

Dans un article paru en 1978 dans « The Bell System Technical Journal », Douglas McIlroy rassemble un certain nombre de maximes qui ont cours dans la communauté des programmeurs et des utilisateurs de Unix et qui en décrivent la philosophie. La première est sans doute la plus connue :

Make each program do one thing well. To do a new job, build afresh rather than complicate old programs by adding new “features.”

Mais voici ce que dit la deuxième :

Expect the output of every program to become the input to another, as yet unknown, program. Don’t clutter output with extraneous information. Avoid stringently columnar or binary input formats. Don’t insist on interactive input.

La plupart des commandes Unix (internes ou externes) respecte ce précepte qui permet de les enchaîner à l’aide de tube (inventé par McIlroy) pour former un pipeline comme dans l’example suivant :

1
dev@vmdev:~ ls | sort

Le symbole | (tube ou pipe) indique que l’on souhaite rediriger la sortie standard de la commande ls vers l’entrée standard de la commande sort comme l’illustre la figure 9.

Enchaîne de la commande ls et sort avec un tube
Fig. 9 – Enchaîne de la commande ls et sort avec un tube

Les tubes sont abondamment utilisés en PowerShell qui en a repris l’idée.