Redirections, filtres et tubes

Entrées et sorties standards

Les programmes et les commandes lancées sous UNIX ont automatiquement à leur disposition une entrée standard (appelée standard in ou stdin) et une sortie standard (appelée, sans grande surprise, standard out ou stdout). Par défaut, l'entrée standard est le clavier (c'est-à-dire que les programmes lisent les données entrées au clavier par l'utilisateur) et la sortie standard est l'écran (c'est à dire qu'un printf() dans un de nos programmes C va résulter en quelque chose de visible à l'écran).

Cette connexion initiale de l'entrée standard vers le clavier et de la sortie standard vers l'écran n'a cependant rien de fatal ou d'obligatoire. Il est possible avant et pendant l'execution d'un programme, de reconnecter stdin et stdout avec autre chose, que ce soit un fichier ou une entrée ou sortie d'un autre programme. La suite de cette page décrit quelques-unes des possibilités.

Concepts d'Unix. Comme son nom le laisse deviner, une des motivations des créateurs d'UNIX était d'unifier le plus possible la gestion des ressources d'un ordinateur. Un des paradigmes de cette ambition peut être résumé en "Tout est fichier". En effet, toute ressource, de l'écran en passant par la webcam à la connexion internet, est représentée par un (pseudo-)fichier par le système opérationnel. L'avantage est clair: Il suffit pour un programme de savoir lire et écrire dans des fichiers, et ledit programme saura en principe imprimer, envoyer des mails, etc. L'élégance et la puissance de ce concept lui ont valu d'être toujours valable sur les Unix modernes comme BSD ou Linux, quarante ans après la création du premier Unixoïde.

Redirections

Les deux opérateurs < et > permettent de rediriger l'entrée ou la sortie standard d'un programme vers un fichier juste avant son lancement.

Redirection de la sortie standard : operateur >

La commande suivante:

ordi:~ > date > toto.txt

n'affiche rien à l'écran, alors que la commande date affiche normalement la date et l'heure. Mais le fichier toto.txt contient maintenant la date! Si on s'imagine un programme comme une boite avec un tube d'entrée et un tube de sortie (voir aussi l'encadré "Comment faire en sorte que..."), l'effet de l'opérateur de redirection > est de connecter le tube sortie sur le fichier toto.txt, alors que normalement il aurait été connecté à l'écran (au terminal).

/!\ Attention /!\

Il faut faire attention au fait que le contenu précédent de toto.txt est perdu si on lance une commande en redirigant la sortie vers lui: toto.txt contiendra la sortie de la commande lancée, mais plus rien de ce qu'il contenait avant.

Cette redirection marche pour tous les programmes, y compris ce que vous avez écrit:

ordi:~ > ls -l > toto.txt
ordi:~ > cat toto.txt # affiche le contenu de toto.txt
ordi:~ > ./simul_pendule.exe > pendule.data

Ceci est très pratique, car vous n'avez plus besoin de vous préoccuper de l'ouverture d'un fichier et de l'utilisation de fprintf(). À la place, vous écrivez le programme en utilisant printf() pour que les résultats s'affichent à l'écran, et vous les redirigez vers un fichiers une fois que vous êtes satisfait du résultat. Derrière les coulisses, printf(...) n'est de toute façon rien d'autre que fprintf(stdout,...), que vous pourriez parfaitement utiliser à la place. Cela vous évite d'avoir à penser au fopen()/fclose().

Comment faire en sorte que ...

... les messages d'information ou d'erreur du programme ne soient pas eux aussi redirigé vers le fichier en même temps que les données ?

Réponse: Chaque programme est en fait équipé d'office d'une deuxième sortie appelée standard error ou stderr qui n'est pas redirigé par l'opérateur >. Il suffit donc d'imprimer les message dans ce tube (avec fprintf(stderr,...)) pour qu'ils arrivent à l'écran!

... le contenu préalable du fichier soit conservé, et que la sortie d'une commande soit juste ajoutée à la fin ?

Réponse: il suffit pour cela d'utiliser l'opérateur >> à la place de l'opérateur >.

redirection de l'entrée standard : operateur <

L'operateur < permet de rediriger l'entrée standard d'un programme (ou d'une commande) qui a besoin qu'on lui donne des information, usuellement données au clavier. Cet opérateur permet de préparer les informations que l'on veut donner au programme en les écrivant dans un fichier texte (par exemple parametres.txt) puis d'appeler le programme en redirigeant l'entrée vers le fichier :

ordi:~ >  programme < parametres.txt

Au lieu d'attendre que l'utilisateur entre les données requises au clavier, il va les chercher dans le fichier parametres.txt. Ce type de fonctionnement permet de gagner beaucoup de temps lorsque le programme nécessite de nombreuses entrées, cela permet également de changer les paramètres d'exécution du programme en ne changeant que ce qui est nécessaire dans le fichier d'entrées. Cela limite énormément les fautes de frappe!

Filtres et "Tubes"

Il existe un opérateur de redirection qui connecte la sortie d'un programme à l'entrée d'un autre programme. Les données "coulent" donc depuis le premier programme par ce qu'on appelle un "tube" (pipe en Anglais) vers l'entrée du deuxième programme. L'opérateur est un trait vertical | entre les programmes. L'intérêt de ce comportement et de pouvoir enchaîner des transformations de données. On appelle filtre tout programme qui lit depuis l'entrée standard, transforme les données, puis les écrit vers la sortie standard. Ainsi, la plupart des programmes et commandes UNIX sont des filtres. L'opérateur | permet de les enchaîner en envoyant la sortie de l'un vers l'entrée de l'autre:

ordi:~ > ls -l | more

Par exemple, si le répertoire courant contient un grand nombre de fichiers dont on veut voir la liste détaillée, la commande ls -l n'est pas satisfaisante car son résultat défile sur l'écran et on ne peut voir les premiers fichiers de la liste. Nous avons vu que l'on pouvait rediriger la sortie de cette commande vers un fichier (ls -l > toto.txt), mais il faut ensuite taper la commande more toto.txt pour observer le résultat écran par écran, puis effacer le fichier toto.txt (rm toto.txt) si on ne veut pas garder cette liste. L'idée des filtres est d'envoyer directement la sortie de ls -l vers l'entrée de more. Cela est réalisé avec l'opérateur tube | dans l'exemple qui précède.

UNIX comporte un grand nombre d'utilitaires (des filtres) que l'on peut associer de cette manière, de sorte qu'il est possible d'effectuer des opérations complexes par des traitements successifs à travers les filtres. À titre d'exemple, la liste des dix plus gros fichiers ou répertoires à l'intérieur du répertoire courant est obtenue par la chaîne

ordi:~ > du -sk *| sort -n -r | head

La commande du affiche la taille des fichiers (options -s: sans rentrer dans les répertoires, -k: en kilo-octets), la transmet à sort qui la trie numériquement (-n; sans cette option, l'ordre alphabétique ferait apparaître 100 après 10 mais avant 20...) et en ordre inversé (-r), puis finalement head n'en garde que les dix premières lignes et jette le reste. Utilisez la commande man sur le fonctionnement des filtres et pour plus d'information sur les options.

Auteur(s) : Anciens, A. Daerr. Dernière modification : Sat Oct 25 19:59:58 2008. [validate XHTML]