bash - xargs rm




¿Hay un equivalente de grep para los switches-print0 y xargs-0? (4)

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?


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.


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 {} + 


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 .







xargs