¿Cómo puedo manejar espacios en los nombres de archivo cuando uso xargs en los resultados de búsqueda?

28

Una de mis prácticas comunes es realizar greps en todos los archivos de cierto tipo, por ejemplo, encontrar todos los archivos HTML que tienen la palabra "rumpus" en ellos. Para hacerlo, yo uso

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

Ocasionalmente, finddevolverá un archivo con un espacio en su nombre como my new file.html. Sin embargo, cuando se xargspasa esto a grep, obtengo estos errores:

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

Puedo ver lo que está pasando aquí: ya sea la tubería o el xargsestá tratando los espacios como delimitadores entre archivos. Sin embargo, por mi vida, no puedo entender cómo prevenir este comportamiento. ¿Se puede hacer con find+ xargs? ¿O tengo que usar un comando completamente diferente?

abeger
fuente

Respuestas:

29

Utilizar

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

p.ej

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

desde la página del manual de búsqueda

-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 es compatible con GoFundMonica
fuente
15

No necesita usar xargs , porque find puede ejecutar comandos por sí mismo. Al hacer esto, no tiene que preocuparse por la shell interpretando caracteres en el nombre.

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

desde la página del manual de búsqueda

-exec command {} +
Esta variante de la acción -exec ejecuta el comando especificado en los archivos seleccionados, pero la línea de comando se crea agregando cada nombre de archivo seleccionado al final; El número total de invocaciones del comando será mucho menor que el número de archivos coincidentes. La línea de comando se construye de la misma manera que xargs construye sus líneas de comando. Solo se permite una instancia de `{} 'dentro del comando. El comando se ejecuta en el directorio de inicio.

Sciurus
fuente
Votaría esto, pero no me queda por hoy, lo haré mañana.
user9517 admite GoFundMonica
1
@Iain: allí tienes (estoy de acuerdo, por cierto).
Eduardo Ivanec
Con solo usar find, todavía te pierdes las características de xargs, además tienes que lidiar con reglas de citas tontas. Vea el argumento -P para xargs si tiene más de un núcleo / CPU.
Slartibartfast
8

Si las versiones find y xarg en su sistema no son compatibles -print0y -0cambian (por ejemplo, AIX find y xargs) puede usar esto:

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

Aquí sed se encargará de escapar de los espacios para xargs.

Jan Ptáčník
fuente
Esto me ayudó porque tenía una larga lista de nombres de archivos que era difícil de producir y que usé varias veces. No puedo ir finda todos de nuevo.
Scott M.