Exemple:
ls | echo
n'imprime rien (une ligne vide, en fait). Je m'attendrais à ce qu'il imprime une liste de fichiers.
ls | grep 'foo'
, en revanche, fonctionne comme prévu (imprime les fichiers avec le nom 'foo' dans leur nom).
Ce que je fais dans ces situations ressemble à quelque chose comme: ls | while read OUT; do echo $OUT; done
mais c'est plutôt lourd.
Pourquoi la tuyauterie fonctionne-t-elle avec certaines commandes mais pas avec d'autres? Comment puis-je contourner ce problème?
Il existe une distinction entre les arguments de ligne de commande et les entrées standard. Un tuyau connectera la sortie standard d'un processus à l'entrée standard d'un autre. Alors
ls | echo
Connecte la sortie standard de ls à l’entrée standard d’écho. Bien d'accord? Eh bien, echo ignore l’entrée standard et dumpera ses arguments en ligne de commande - qui ne sont dans ce cas aucunes - sa propre sortie standard. La sortie: rien du tout.
Il y a quelques solutions dans ce cas. La première consiste à utiliser une commande qui lit stdin et effectue un dump sur stdout, tel que cat.
ls | cat
Will 'work', en fonction de votre définition du travail.
Mais qu'en est-il du cas général. Ce que vous voulez vraiment, c'est convertir stdout d'une commande en arguments de ligne de commande d'une autre. Comme d'autres l'ont déjà dit, xargs
est l'outil d'assistance canonique dans ce cas, lisant ses arguments de ligne de commande pour une commande à partir de son stdin et créant des commandes à exécuter.
ls | xargs echo
Vous pouvez également convertir cela en utilisant la commande de substitution $()
echo $(ls)
Feriez aussi ce que vous voulez.
Ces deux outils sont assez fondamentaux pour les scripts Shell, vous devriez apprendre les deux.
Pour être complet, comme vous l'avez indiqué dans la question, l'autre méthode de base pour convertir stdin en arguments de ligne de commande est la commande intégrée read
du shell. Il convertit les "mots" (les mots définis par la variable IFS
) en une variable temporaire que vous pouvez utiliser dans toutes les exécutions de commandes.
ls | echo
affiche uniquement une ligne vierge car echo
ne lit aucune entrée; La dernière commande du pipeline est en fait une variable echo
qui n'imprime qu'une ligne vierge.
Généralement:
a | b
s'assure que la sortie de a
devienne l'entrée de b
. Je vous suggère de lire la section Pipelines
de man bash
.
Si vous voulez vraiment utiliser ls
et echo
ensemble, voici quelques exemples (plutôt inutiles):
ls | xargs -L 1 echo
echo `ls`
for i in `ls` ; do echo $i ; done
Si vous voulez echo
la commande ls
essayez:
ls | xargs echo
Ceci appellera echo
avec la sortie de ls
.
Pourquoi ne pas simplement utiliser:
echo `ls`
Ou beaucoup plus sûr:
echo "`ls -lrt`"