Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Dans un Script BASH comment lire un Pipe ??

1 réponse
Avatar
projlin
Bonjour,

Dans un Script bash comment lire un Pipe ??

Je m'explique je fait sous linux un script que j'appelle comme cela

Exemple : ls | mon_script_bash
Donc je suis sensé dans cet exemple récupérer pleins de texte, dans
mon script ?

Comment faire ??

Ce qui est passé par un Pipe n'est pas vu comme un argument ?

Merci de votre aide

Bon si en plus il y a une âme charitable en plus d'être calée j'ai la
même question Dans un programme en C !

Merci

1 réponse

Avatar
Stephane Chazelas
2003-11-23, 02:33(-08), :
[...]
Exemple : ls | mon_script_bash
Donc je suis sensé dans cet exemple récupérer pleins de texte, dans
mon script ?

Comment faire ??

Ce qui est passé par un Pipe n'est pas vu comme un argument ?
[...]


Sous Unix, une commande (que ce soit un script ou autre) est
démarré dans un certain « environnement d'exécution ».

Ça se fait au travers de l'appel système "execle". "l" pour
"liste d'arguments", "e" pour environnement. En plus de ça,
après un "exec", un processus garde sa liste file descriptors
(qui indentifient chacun un fichier ouvert (en lecture ou
écriture).

Donc, on peut dire que l'environnement "de démarrage" d'une
commande, c'est
- les arguments
- l'environnement (les variables d'environnement)
- les fichiers ouverts (fichier au sens large du terme)

Un shell est un outil qui permet à l'utilisateur d'écrire des
lignes de commandes et qui, à partir de celles-ci, lance des
commandes (avec execle donc).

La ligne de commande a une syntaxe bien particulière qui permet
de jouer sur les trois tableaux (args, env, files).

La ligne de commande la plus simple, c'est par exemple:

ls

qui va lancer la commande "/bin/ls" avec un seul argument
(l'argument 0) : "ls", avec comme environnement l'environnement
courant (c.a.d., celui que le shell lui-même a reçu lors du
execle qui l'a lancé lui, plus les "(des)assignations de
variables" d'environnement qui ont été faites depuis suivant une
autre syntaxe qui est aussi particulière au shell), et avec comme
fichiers ouverts les mêmes que pour le shell (c'est à dire
probablement seulement les fd 0, 1 et 2 ouverts respectivement
en lecture, écriture et écriture sur le /dev/tty... qui désigne
le terminal courant).

Par convention, "ls" écrit ce qu'il a à écrire (la liste des
fichiers du répertoire courant) sur le "file descriptor" 1 qu'on
appelle la sortie standard (stdout pouvant désigner le fd 1 ou
le fichier [la resource] qui lui est associé) et quand ce sont
des messages d'erreur sur le "file descritor" 2 qu'on appelle
sortie d'erreur (stderr). C'est pour ça qu'il est important que
les fd 0, 1 et 2 soient ouverts quand on démarre une commande.

Plus compliqué:

POSIXLY_CORRECT=1 ls -s a b 2> /dev/null 3>&- < /tmp/a

Ici, on joue sur les trois tableau: args, env et files.

On lance /bin/ls avec 4 arguments: "ls", "-s", "a" et "b" avec
l'environnement courant + POSIXLY_CORRECT=1 et avec le fd 2
ouvert en écriture sur /dev/null et le fd 3 fermé (pour le cas
où il aurait été ouvert avant) et le fd 0 ouvert en lecture sur
/tmp/a. 0 est le file descriptor de l'entrée standard, c'est à
dire que quand les commandes ont quelque chose à lire (en
principe, de l'utilisateur) elles le lisent par convention sur
ce file descriptor là. ls ne lit rien (ne demande rien à
l'utilisateur), donc "rediriger" l'"entrée standard" /depuis/ un
fichier ou autre chose ne sert pas à grand chose.

Un "|" dans un shell est encore autre chose. Elle permet de
relier deux commandes (il y a alors deux lignes de commande
dans le format que je décris au dessus de part et d'autre)
ensemble.

Un pipe(2), sous Unix peut-être vu comme, ben, un tuyau. Ça
fournit une paire de "file descriptors" où ce qu'on écrit sur un
(qui pointe sur l'entree du tuyay) devient disponible en lecture
sur l'autre (qui pointe sur l'autre bout du tuyau).

Dans:

cmd1 | cmd2

le shell lance deux processus à la fois dans lesquelles sont
lancée les deux commandes avec, pour cmd1 son file descritor
(fd) 1 pointant sur l'entrée du tube et pour cmd2 le fd 0
pointant sur la sortie du tube.

Comme on a vu que les commandes, par convention, écrivaient sur
leur fd 1 et lisaient sur leur fd 0. Ça revient à dire que cmd2
va lire (si elle lit quelque chose) ce que cmd1 va écrire (si
elle écrit quelque chose).

Donc, tu dois comprendre maintenant, que dans

cmd | ton-script

Si tu veux que les commandes qui sont dans ton script lisent ce
que cmd écrit, il faut qu'elles lisent sur le fd 0. Ça tombe
bien, c'est ce qu'elles font automatiquement par convention !

Si ton script contient:

#! /bin/sh
wc -l

ls | ton-script

va executer /bin/ls avec le fd 1 sur l'entree du tube. En même
temps, il va exécuter "/bin/sh" avec en paramètres "/bin/sh" et
"ton-script" avec le fd 0 sur la sortie du tube.

Ce nouveau shell va ensuite exécuter /bin/wc avec en paramètres
"wc" et "-l" et avec le même fd 0.

wc, qui est une commande qui lit sont entrée standard (fd 0)
pour en compter le nombre de lignes/mots/bytes/characters et
l'afficher sur sa sortie standard (fd 1) va donc compter le
nombre de lignes dans ce qu'écrit "ls" et l'afficher à l'écran
(ce sur quoi pointe son fd 1).

--
Stéphane ["Stephane.Chazelas" arobase "free.fr"]