Lorsque j'exécute le script Bash
suivant, je m'attends à ce qu'il imprime Hello
. Au lieu de cela, il imprime une ligne vierge et se ferme.
echo 'Hello' | echo
Pourquoi piping
la sortie de echo
vers echo
ne fonctionne-t-elle pas?
echo
affiche tous ses arguments. Il ne lit pas dans stdin
. Donc, le second echo
imprime tous ses arguments (aucun) et se ferme, en ignorant le Hello
sur stdin
.
Pour un programme qui lit son stdin
et l’affiche dans stdout
, utilisez cat
:
$ echo Hello | cat
Hello
Vous ne semblez pas comprendre les pipes. Dans ce cas, on les appelle plus correctement des canaux anonymes , car ils n'ont pas de nom (il existe également des tubes nommés ). Les canaux anonymes ne fonctionnent qu'entre des processus associés, par exemple des processus avec le même parent.
Les pipes font partie du système IO résultant de la bibliothèque d'exécution C. Ces flux sont mis en mémoire tampon (il existe un Par défaut, un canal connecte simplement le tampon de sortie d’un processus au tampon d’entrée d’un autre.
Les trois premiers flux utilisés (appelés descripteurs de fichier ) sont numérotés 0, 1 et 2. Le premier, 0, est appelé entrée standard ou stdin
(le nom utilisé en C). Par défaut, il est connecté au clavier, mais il peut être redirigé à l'aide du symbole <
Ou par le nom du programme situé à droite d'un tuyau.
La seconde, 1, est connue sous le nom de sortie standard ou stdout
. Par défaut, il est connecté à l'écran du terminal, mais peut être redirigé à l'aide du symbole >
Ou du nom du programme situé à gauche d'un tuyau.
Alors:
echo 'Hello' | echo
prend la sortie standard de echo
et la transmet à l'entrée standard de echo
. Mais echo
ne lit pas stdin! Donc rien ne se passe.
Les programmes de filtrage traitent les noms de fichiers spécifiés sur la ligne de commande. Si aucun nom de fichier n'est donné, ils lisent stdin. Les exemples incluent cat
, grep
et sed
, mais pasecho
. Par exemple:
echo 'Hello' | cat
affichera 'Bonjour', et le cat
est inutile (c'est souvent le cas).
echo 'Hello' | cat file1
va ignorer la sortie de echo
et simplement afficher le contenu de fichier1. Rappelez-vous que stdin n'est lu qu'en l'absence de nom de fichier.
Que pensez-vous que cela affiche?
echo 'Hello' | cat < file1 file2
et pourquoi?
Enfin, le troisième flux, 2, est appelé erreur type ou stderr
, et celui-ci est sans tampon . Les pipes sont ignorés car ils ne fonctionnent qu'entre stdin et stdout. Cependant, vous pouvez rediriger stderr pour utiliser stdout (voir man dup2
):
myprog 2>&1 | anotherprog
Le 2>&1
Signifie "rediriger le descripteur de fichier 2 au même endroit que le descripteur 1".
Le comportement ci-dessus est normal. Cependant, un programme peut remplacer tout cela s'il le souhaite. Il pourrait lire le descripteur de fichier 2, par exemple. J'ai omis de nombreux autres détails, y compris d'autres formes de redirection telles que la substitution de processus et ici des documents .
La tuyauterie ne peut être faite que pour les commandes prenant des entrées de stdin. Mais l'écho ne prend pas de stdin. Il faudra entrer l'argument et l'imprimer. Donc, cela ne fonctionnera pas. Pour faire écho, vous pouvez faire quelque chose comme echo $(echo 'hello')
C’est parce que echo
(à la fois construit et /bin/echo
) ne lis rien de stdin
.
Utilisez cat
à la place:
echo 'Hello' | cat
Hello
Ou sans tuyaux:
cat <<< 'Hello'