¿Cómo paso una lista de archivos a grep?

98

Estoy usando findy obteniendo una lista de archivos que quiero greppasar. ¿Cómo canalizo esa lista grep?

Arcabard
fuente

Respuestas:

116

Bueno, el caso genérico que funciona con cualquier comando que escriba en stdout es usar xargs, lo que le permitirá adjuntar cualquier número de argumentos de línea de comando al final de un comando:

$ find … | xargs grep 'search'

O para incrustar el comando en su greplínea con backticks o $(), que ejecutará el comando y sustituirá su salida:

$ grep 'search' $(find …)

Tenga en cuenta que estos comandos no funcionan si los nombres de los archivos contienen espacios en blanco u otros "caracteres extraños" ( \'"para xargs, \[*?para $(find …)).


Sin embargo, en el caso específico de findla capacidad de ejecutar un programa en los argumentos dados, está incorporado:

$ find … -exec grep 'search' {} \;

Todo entre -execy ;es el comando a ejecutar; {}se reemplaza con el nombre de archivo encontrado por find. Eso ejecutará un separado greppara cada archivo; dado que greppuede tomar muchos nombres de archivo y buscarlos todos, puede cambiar a ;to +para decirle a find que pase todos los nombres de archivo coincidentes a la grepvez:

$ find … -exec grep 'search' {} \+
Michael Mrozek
fuente
1
Debe tenerse en cuenta que las dos primeras formas no funcionan con nombres de archivos que contienen espacios.
enzotib
1
Yo prefiero find ... -type f -print0 | xargs -r0 grep 'search' /dev/null. QED Si bien -exec +es muy eficiente, no existe en todas las versiones de find.
Arcege
Lamentablemente, no puedo verificar que corrijas 3 veces.
Arcabard
3
Sugiero usar el -exec, en lugar de el xargs. Si se utiliza el -execen find, se creará una sola concha para grep para el contenido. Si usa el xargs, creará dos shells: uno para el findy el otro para el xargs.
2
Por experimento encuentro que la $ find … -exec grep 'search' {} \+forma es mucho más rápida.
gogoud
9

Algunas versiones de grep(por ejemplo, en Linux no integrado o BSD o Mac OS X) tienen una -ropción para realizar una búsqueda recursiva. En OpenBSD, use -R(y no hay --excludecomo en el ejemplo a continuación). Esto cubre combinaciones simples de findcon grep.

Si su implementación no tiene el -Rindicador, o si desea criterios de coincidencia de archivos más sofisticados, puede usar el -execprimario de findpara que se ejecute grep. Unos más antiguas findimplementaciones no soportan -exec... +; en estos sistemas, use un en ;lugar del +(esto llamará grepuna vez por archivo, por lo que será más lento, pero de lo contrario el resultado será el mismo). Tenga en cuenta el /dev/nulltruco para hacer grepque se muestre el nombre del archivo incluso si se llama en un solo archivo (GNU grep y FreeBSD / NetBSD / OSX grep tienen una -Hopción para lograr el mismo efecto).

find . -type f -name '*.o' -prune -o -exec grep 'needle' /dev/null {} +
grep -r --exclude='*.o' 'needle' .
Gilles
fuente
2
GNU greptiene la -Hopción de imprimir siempre el nombre del archivo.
enzotib