bash - xargs grep
¿Hay un equivalente de grep para los switches-print0 y xargs-0? (6)
Utilice GNU Grep''s --null
Flag
De acuerdo con la documentación de GNU Grep , puede usar el control de prefijo de la línea de salida para manejar los caracteres ASCII NUL de la misma manera que find y xargs .
-Z
--nulo
Genere un byte cero (el carácter ASCII NUL) en lugar del carácter que normalmente sigue a un nombre de archivo. Por ejemplo, ''grep -lZ'' genera un byte cero después de cada nombre de archivo en lugar de la nueva línea habitual. Esta opción hace que el resultado sea inequívoco, incluso en presencia de nombres de archivo que contienen caracteres inusuales como nuevas líneas. Esta opción se puede usar con comandos como ''buscar -print0'', ''perl -0'', ''ordenar -z'' y ''xargs -0'' para procesar nombres de archivo arbitrarios, incluso aquellos que contienen caracteres de nueva línea.
Use tr
de GNU Coreutils
Como el OP señala correctamente, este indicador es más útil cuando se manejan nombres de archivo en entrada o salida. Para convertir realmente la salida grep para usar caracteres NUL como finales de línea, necesitaría usar una herramienta como sed o tr para transformar cada línea de salida. Por ejemplo:
find /etc/passwd -print0 |
xargs -0 egrep -Z ''root|www'' |
tr "/n" "/0" |
xargs -0 -n1
Esta canalización usará NUL para separar nombres de archivo de find y luego convertir líneas nuevas a NUL en las cadenas devueltas por egrep . Esto pasará las cadenas terminadas en NUL al siguiente comando en la canalización, que en este caso es simplemente xargs convirtiendo la salida nuevamente en cadenas normales, pero podría ser lo que usted desee.
A menudo quiero escribir comandos como este (en zsh
, si es relevante):
find <somebasedirectory> | /
grep stringinfilenamesIwant | /
grep -v stringinfilesnamesIdont | /
xargs dosomecommand
(o combinaciones más complejas de greps)
En los últimos años, find
ha agregado el -print0
, y xargs ha agregado -0
, lo que permite manejar los archivos con espacios en el nombre de una manera elegante mediante nombres de archivo con terminación nula, lo que permite esto:
find <somebasedirectory> -print0 | xargs -0 dosomecommand
Sin embargo, grep
(al menos la versión que tengo, GNU grep 2.10 en Ubuntu), no parece tener un equivalente para consumir y generar líneas terminadas en nulo; tiene --null
, pero eso solo parece estar relacionado con el uso de -l
para dar salida a nombres cuando se buscan archivos directamente con grep.
¿Existe una opción o combinación de opciones equivalente que pueda usar con grep? Alternativamente, ¿hay una manera fácil y elegante de expresar mi pipa de comandos simplemente usando find -regex
, o quizás Perl?
Como ya está utilizando GNU find
, puede usar sus capacidades internas de coincidencia de patrones de expresión regular en lugar de grep
, por ejemplo:
find <somebasedirectory> -regex ".*stringinfilenamesIwant.*" ! -regex ".*stringinfilesnamesIdont.*" -exec dosomecommand {} +
En lugar de usar un tubo, puede usar find -exec
con el +
terminador. Para encadenar múltiples comandos juntos, puede generar un shell en -exec
.
find ./ -type f -exec bash -c ''grep "$@" | grep -v something | xargs dosomething'' -- {} +
La versión más nueva de la fuente grep de GNU ahora puede usar -z
/ - --null
para separar la salida mediante caracteres nulos, mientras que anteriormente solo funcionaba junto con -l
:
http://git.savannah.gnu.org/cgit/grep.git/commit/?id=cce2fd5520bba35cf9b264de2f1b6131304f19d2
Esto significa que su problema se resuelve automáticamente al usar la versión más nueva.
Utilizar
find <somebasedirectory> -print0 | /
grep -z stringinfilenamesIwant | /
grep -zv stringinfilesnamesIdont | /
xargs -0 dosomecommand
Sin embargo, el patrón puede no contener nueva línea, ver informe de errores .
find <somebasedirectory> -print0 | xargs -0 -I % grep something ''%''