Unix Pipes pour l’argument de commande

Je cherche un aperçu de la façon dont les pipes peuvent être utilisées pour transmettre la sortie standard comme arguments pour d’autres commandes.

Par exemple, considérons ce cas:

ls | grep Hello 

La structure de grep suit le modèle: grep SearchTerm PathOfFileToBeSearched . Dans le cas que j’ai illustré, le mot Hello est pris comme SearchTerm et le résultat de ls est utilisé comme fichier à rechercher. Mais que faire si je veux le changer? Que faire si je veux que la sortie standard de ls soit le SearchTerm, avec l’argument suivant grep étant PathOfFileToBeSearched ? D’une manière générale, je veux contrôler quel argument le canal remplit avec la sortie standard de la commande précédente. Est-ce possible ou dépend-il de la manière dont le script de la commande (par exemple, grep ) a été écrit?

Je vous remercie beaucoup pour votre aide!

Il existe essentiellement deux options pour cela: la substitution de commandes shell et xargs . Brian Agnew vient d’écrire sur le premier. xargs est un utilitaire qui prend son stdin et le transforme en arguments d’une commande à exécuter. Donc tu pourrais courir

 ls | xargs -n1 -J % grep -- % PathOfFileToBeSearched 

et pour chaque fichier grep -e filename PathOfFileToBeSearched par ls , exécutez grep -e filename PathOfFileToBeSearched pour grep pour le nom de grep -e filename PathOfFileToBeSearched par ls dans l’autre fichier que vous spécifiez. Ceci est une invocation inhabituelle de xargs ; En général, il est utilisé pour append un ou plusieurs arguments à la fin d’une commande, alors qu’ici, il doit append exactement un argument à un endroit spécifique. J’ai donc utilisé les arguments -n et -J pour arranger cela. L’usage le plus courant serait quelque chose comme

 ls | xargs grep -- term 

pour rechercher tous les fichiers générés par ls pour term . Bien sûr, si vous ne voulez que des fichiers dans le répertoire actuel, vous pouvez le faire plus simplement sans pipeline:

 grep -- term * 

et de même dans votre arrangement inversé,

 for filename in *; do grep -- "$@" PathOfFileToBeSearched done 

Il y a un xargs important avec xargs : les caractères d’espacement dans les noms de fichiers générés par ls ne seront pas trop bien traités. Pour ce faire, à condition d’avoir des utilitaires GNU, vous pouvez utiliser find place.

 find . -mindepth 1 -maxdepth 1 -print0 | xargs -0 -n1 -J % grep -- % PathOfFileToBeSearched 

utiliser des caractères NUL pour séparer les noms de fichiers au lieu des espaces

grep lui-même sera construit de telle sorte que si vous n’avez pas spécifié de nom de fichier, il ouvrira stdin (et obtiendra ainsi la sortie de ls ). Il n’y a pas de véritable mécanisme générique ici – simplement une convention.

Si vous souhaitez que le résultat de ls soit le terme de recherche, vous pouvez le faire via le shell. Utilisez un sous-shell et une substitution pour:

 $ grep $(ls) filename.txt 

Dans ce scénario, ls est exécuté dans un sous-shell et sa sortie standard est capturée et insérée dans la ligne de commande en tant qu’argument de grep . Notez que si la sortie ls contient des espaces, cela entraînera une confusion pour grep .