J'essaie d'exécuter grep sur une liste de quelques centaines de fichiers:
$ head -n 3 <(cat files.txt)
admin.php
ajax/accept.php
ajax/add_note.php
Cependant, même si je recherche une chaîne que je connais dans les fichiers, ce qui suit ne recherche pas les fichiers:
$ grep -i 'foo' <(cat files.txt)
$ grep -i 'foo' admin.php
The foo was found
Je connais le -f
drapeau qui lira les motifs d'un fichier. Mais comment lire les fichiers d'entrée ?
J'avais envisagé l'horrible solution de contournement de la copie des fichiers dans un répertoire temporaire qui cp
semble prendre en charge le <(cat files.txt)
format, et à partir de là, en saluant les fichiers. Shirley, il y a une meilleure façon.
la source
while
pouvait recevoir les lignes de file.txt en tant que telles.while
ne reçoit pas exactement les lignes du fichier, leread
fait;while
nous permet simplement de faire cela en boucle. La boucle se termine en cas d'read
échec (c'est-à-dire renvoie un code retour différent de zéro), normalement en raison de la fin du fichier atteinte.IFS= read -r filename
,read filename
c'est autre chose.-H
s'agit d'une extension GNU. Vous en manquez--
.en supposant que les fichiers sont vides ou délimités par des sauts de ligne (où les guillemets ou les barres obliques inverses peuvent être utilisés pour échapper à ces séparateurs). Avec GNU,
xargs
vous pouvez spécifier le délimiteur avec-d
(ce qui désactive alors la gestion des citations).en supposant que les fichiers sont séparés par des espaces, des tabulations ou des sauts de ligne (aucun moyen de les échapper bien que vous puissiez choisir un séparateur différent en l'affectant à
IFS
). Celui-ci échouera si la liste des fichiers est trop grande sur la plupart des systèmes.Ceux-ci supposent également qu'aucun des fichiers n'est appelé
-
.la source
$(< file)
au lieu de$(cat file)
, au moins dansbash
etzsh
.Pour lire une liste de noms de fichiers depuis stdin, vous pouvez utiliser
xargs
. Par exemple,Par défaut,
xargs
lit les éléments de l'entrée standard, délimités par des blancs. Le lui-d'\n'
indique d'utiliser la nouvelle ligne comme délimiteur d'argument, afin de pouvoir gérer les noms de fichiers contenant des espaces. (Comme le souligne Stéphane Chazelas, c'est une extension GNU). Cependant, il ne supportera pas les noms de fichiers contenant des retours à la ligne; nous aurions besoin d'une approche un peu plus compliquée pour les gérer.FWIW, cette approche est un peu plus rapide qu'une
while read
boucle, car laread
commande de bash est très lente - elle lit ses données caractère par caractère, tandis qu'ellexargs
lit son entrée plus efficacement. En outre,xargs
n'appelle lagrep
commande autant de fois que nécessaire, chaque appel recevant plusieurs noms de fichier, et c'est plus efficace que d'appelergrep
individuellement pour chaque nom de fichier.Consultez la page de manuel de xargs et la page d'informations de xargs pour plus de détails.
la source
xargs
peut lire des éléments d'un fichier (comme votrefiles.txt
liste) avec son option:Cela devrait donc aussi fonctionner:
ou pour les espaces dans les noms de fichiers
la source
Vous pouvez également faire un for mais l'exemple d'Orion est le plus simple:
(Pour chaque fichier répertorié dans le fichier files.txt, exécutez la commande grep dessus.)
la source