linux - hay - bash demasiados argumentos
¿Cómo puedo grep mientras evito ''Demasiados argumentos'' (5)
Esta pregunta ya tiene una respuesta aquí:
Estaba tratando de limpiar algunos correos electrónicos no deseados y encontré un problema. La cantidad de archivos en la cola era tan grande que mi comando habitual no podía procesar. Me daría un error sobre demasiados argumentos.
Yo suelo hacer esto
grep -i [email protected] 1US* | awk -F: ''{print $1}'' | xargs rm
1US * puede ser cualquier cosa entre 1US [a-zA-Z]. Lo único que podía hacer era ejecutar este horrible artilugio. Es un archivo, con 1USa, 1USA, 1USb, etc., a través de todo el alfabeto. Sé que tiene que ser una forma de ejecutar esto de manera más eficiente.
grep -s $SPAMMER /var/mailcleaner/spool/exim_stage1/input/1USa* | awk -F: ''{print $1}'' | xargs rm
grep -s $SPAMMER /var/mailcleaner/spool/exim_stage1/input/1USA* | awk -F: ''{print $1}'' | xargs rm
Usar xargs es más eficiente que usar "find ... -exec grep" porque tienes menos creaciones de procesos, etc.
Una forma de hacerlo sería:
ls 1US* | xargs grep -i [email protected] | awk -F: ''{print $1}'' | xargs rm
Pero más fácil sería:
find . -iname "1US*" -exec rm {} /;
Ejecuta varias instancias de grep. En lugar de
grep -i [email protected] 1US* | awk ''{...}'' | xargs rm
hacer
(for i in 1US*; do grep -li user@domain "$i"; done) | xargs rm
Tenga en cuenta el indicador -l, ya que solo queremos el nombre de archivo de la coincidencia. Esto acelerará grep (finalizará en la primera coincidencia) y hará que su script awk no sea necesario. Esto podría mejorarse verificando el estado de retorno de grep y llamando a rm, sin usar xargs (xargs es muy frágil, IMO). Te daré la mejor versión si lo preguntas.
Espero eso ayude.
El argumento -exec
para find
es útil aquí, lo he usado yo mismo en situaciones similares.
P.ej
# List the files that match
find /path/to/input/ -type f -exec grep -qiF [email protected] /{/} /; -print
# Once you''re sure you''ve got it right
find /path/to/input/ -type f -exec grep -qiF [email protected] /{/} /; -delete
Usa find
y un loop en lugar de xargs
.
find . -name ''1US*'' | /
while read x; do grep -iq user@domain "$x" && rm "$x"; done
Esto utiliza pipes y loops en lugar de argumentos (tanto para grep
como rm
) y evita problemas relacionados con los límites en los argumentos.
puede usar find
para encontrar todos los archivos cuyo nombre comience con el patrón ''1US''. Luego puede canalizar la salida a xargs, que se ocupará de que la lista de argumentos no crezca demasiado y maneje la llamada grep. Tenga en cuenta que he usado un nullbyte para separar nombres de archivo para xargs. Esto evita problemas con nombres de archivos problemáticos . ;)
find -maxdepth 1 -name ''1US*'' -printf ''%f/0'' | xargs -0 grep -u user@domain | awk ...