Comment puis-je gérer les espaces dans les noms de fichiers lors de l'utilisation de xargs sur les résultats de recherche?

28

Une de mes pratiques courantes consiste à effectuer des greps sur tous les fichiers d'un certain type, par exemple, trouver tous les fichiers HTML qui contiennent le mot "rumpus". Pour ce faire, j'utilise

find /path/to -name "*.html" | xargs grep -l "rumpus"

Occasionnellement, findretournera un fichier avec un espace dans son nom tel que my new file.html. Cependant, une fois xargstransmis à grep, j'obtiens ces erreurs:

grep: /path/to/bad/file/my: No such file or directory
grep: new: No such file or directory
grep: file.html: No such file or directory

Je peux voir ce qui se passe ici: le tuyau ou le xargstraite les espaces comme des délimiteurs entre les fichiers. Pour la vie de moi, cependant, je ne peux pas comprendre comment empêcher ce comportement. Peut-on le faire avec find+ xargs? Ou dois-je utiliser une commande entièrement différente?

abeger
la source

Réponses:

29

Utilisation

find ... -print0 | xargs -0 ...

par exemple

find /path/to -name "*.html"  -print0 | xargs -0  grep -l "rumpus"

à partir de la page de manuel find

-print0
          True; print the full file name on the standard  output,  followed
          by  a  null  character  (instead  of  the  newline character that
          ‘-print’ uses).  This allows file names that contain newlines  or
          other  types  of  white space to be correctly interpreted by pro-
          grams that process the find output.  This option  corresponds  to
          the ‘-0’ option of xargs.
user9517 prend en charge GoFundMonica
la source
15

Vous n'avez pas besoin d'utiliser xargs , car find peut exécuter les commandes lui-même. En faisant cela, vous n'avez pas à vous soucier de l'interpréteur de caractères dans le nom.

find /path/to -name "*.html" -exec grep -l "rumpus" '{}' +

à partir de la page de manuel find

-exec command {} +
Cette variante de l'action -exec exécute la commande spécifiée sur les fichiers sélectionnés, mais la ligne de commande est créée en ajoutant à la fin chaque nom de fichier sélectionné; le nombre total d'appels de la commande sera bien inférieur au nombre de fichiers correspondants. La ligne de commande est construite de la même manière que xargs construit ses lignes de commande. Une seule instance de `{} 'est autorisée dans la commande. La commande est exécutée dans le répertoire de départ.

sciurus
la source
Je voterais en faveur de cela, mais je ne suis pas parti pour aujourd'hui - je le ferai demain.
user9517 prend en charge GoFundMonica
1
@Iain - voilà (je suis d'accord, au fait).
Eduardo Ivanec
En utilisant simplement find, vous manquez toujours les fonctionnalités de xargs, et vous devez faire face à des règles de citation idiotes. Voir l'argument -P de xargs si vous avez plusieurs cœurs / CPU.
Slartibartfast
8

Trouvez et si les versions xarg sur votre système ne prend pas en charge -print0et les -0commutateurs (par exemple trouver AIX et xargs) vous pouvez utiliser ceci:

find /your/path -name "*.html" | sed 's/ /\\ /g' | xargs grep -l "rumpus"

Ici sed prendra soin de s'échapper des espaces pour xargs.

Jan Ptáčník
la source
Cela m'a aidé car j'avais une longue liste de noms de fichiers difficiles à produire que j'ai utilisée plusieurs fois. Je ne peux pas findtout recommencer.
Scott M.