Question Comment diriger la sortie de commande vers d'autres commandes?


Exemple:

ls | echo n'imprime rien (une ligne vide, en fait). Je m'attendais à ce qu'il imprime une liste de fichiers.

ls | grep 'foo', d'autre part, fonctionne comme prévu (imprime les fichiers avec «foo» dans leur nom).

Ce que je fais dans ces situations est quelque chose comme:       ls | while read OUT; do echo $OUT; done mais c'est plutôt encombrant.

Pourquoi la tuyauterie fonctionne-t-elle avec certaines commandes, mais pas avec d'autres? Comment puis-je contourner ce problème?


76
2017-09-16 13:40


origine


Qu'attendez-vous ls | echo faire? pourquoi ne pas simplement courir ls? - theomega
J'ai utilisé l'exemple le plus simple qui illustre mon propos. J'ai en fait rencontré ce problème lorsque j'essayais de créer une ligne simple qui afficherait des objets git dans le magasin d'objets et leur type. Donc, j'ai canalisé les identifiants d'objets vers git cat-file, mais ça n'a pas marché. Apparemment, echo a le même comportement, donc je l'ai utilisé comme exemple. - Mihai Rotaru
regardez aussi la commande -n pour xargs, elle indique combien d’arguments mettre sur la sous-commande. `... | xargs -n1 git cat-file` - Rich Homolka


Réponses:


Il y a une distinction entre les arguments de ligne de commande et l'entrée standard. Un tube 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 de l'écho. Bien d'accord? Eh bien, echo ignore l'entrée standard et videra ses arguments de ligne de commande - qui ne sont pas dans ce cas à - sa propre sortie standard. La sortie: rien du tout.

Il y a quelques solutions dans ce cas. L'une consiste à utiliser une commande qui lit stdin et vide sur stdout, comme cat.

ls | cat

Cela fonctionnera selon 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 la ligne de commande d'un autre. Comme d'autres l'ont dit, xargs est l'outil d'aide canonique dans ce cas, la lecture de sa ligne de commande args pour une commande de son stdin, et la construction de commandes à exécuter.

ls | xargs echo

Vous pourriez aussi convertir ceci en utilisant la commande de substitution $()

echo $(ls)

Serait également faire ce que vous voulez.

Ces deux outils sont assez importants 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 fonction intégrée du shell. read commander. Il convertit les "mots" (mots définis par le IFS variable) à une variable temporaire, que vous pouvez utiliser dans n'importe quelle exécution de commande.


105
2017-09-16 14:16



Une réponse très utile et informative, merci! J'apprends actuellement bash, et j'ai déjà vu la notation xargs et la notation $ (*), mais je n'y ai pas prêté beaucoup d'attention. Maintenant, je sais à quel point ils sont importants et vont certainement les examiner. - Mihai Rotaru
xargs était peut-être ce que recherchait OP. - Iktys


ls | echo imprime juste une ligne vide parce que echo ne lit aucune entrée; la dernière commande du pipeline est en fait echo qui n'imprime rien d'autre qu'une ligne blanche.

Généralement:

a | b

s'assure que la sortie de a devenir l'entrée de b. Je vous suggère de lire le Pipelines section 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

16
2017-09-16 13:54





Si tu veux echo la ls commande essayer:

ls | xargs echo

Cela va appeler echo avec la sortie de ls.


7
2017-09-16 14:03



Ou ls | xargs -I {} echo {} si vous voulez qu'il soit appelé pour chaque ligne individuellement - Alex Abdugafarov


Pourquoi ne pas simplement utiliser:

echo `ls`

Ou beaucoup plus sûr:

echo "`ls -lrt`"

3
2017-11-09 09:48



Ou même juste echo *. - Kazark