Tengo un directorio con ~1 millón de archivos y necesito buscar patrones particulares. Sé cómo hacerlo para todos los archivos:
find /path/ -exec grep -H -m 1 'pattern' {} ;
No se desea la salida completa (demasiado lenta). Varios primeros accesos están bien, así que traté de limitar el número de líneas:
find /path/ -exec grep -H -m 1 'pattern' {} ; | head -n 5
Esto da como resultado 5 líneas seguidas de
find: `grep' terminated by signal 13
y find
continúa trabajando. Esto está bien explicado aquí. Intenté quit
acción:
find /path/ -exec grep -H -m 1 'pattern' {} ; -quit
Esto genera solo la primera coincidencia.
¿Es posible limitar la salida de búsqueda con un número específico de resultados (como proporcionar un argumento para quit
similar a head -n
)?
Respuesta aceptada:
Como ya está usando extensiones GNU (-quit
, -H
, -m1
), también podría usar GNU grep
‘s -r
opción, junto con --line-buffered
por lo que genera las coincidencias tan pronto como se encuentran, por lo que es más probable que un SIGPIPE lo elimine tan pronto como escriba la sexta línea:
grep -rHm1 --line-buffered pattern /path | head -n 5
Con find
, probablemente necesites hacer algo como:
find /path -type f -exec sh -c '
grep -Hm1 --line-buffered pattern "[email protected]"
[ "$(kill -l "$?")" = PIPE ] && kill -s PIPE "$PPID"
' sh {} + | head -n 5
Es decir, envuelva grep
en sh
(todavía desea ejecutar como pocos grep
invocaciones posibles, de ahí el {} +
) y tener sh
matar a su padre (find
) cuando grep
muere de un SIGPIPE.
Otro enfoque podría ser usar xargs
como alternativa a -exec {} +
. xargs
sale de inmediato cuando un comando que genera muere de una señal, así que en:
find . -type f -print0 |
xargs -r0 grep -Hm1 --line-buffered pattern |
head -n 5
(-r
y -0
siendo extensiones GNU). Tan pronto como grep
escribe en la tubería rota, tanto grep
y xargs
saldrá y find
también se cerrará la próxima vez que imprima algo después de eso. Ejecutando find
bajo stdbuf -oL
podría hacer que suceda antes.
Una versión POSIX podría ser:
trap - PIPE # restore default SIGPIPE handler in case it was disabled
RE=pattern find /path -type f -exec sh -c '
for file do
awk '''
$0 ~ ENVIRON["RE"] {
print FILENAME ": " $0
exit
}''' < "$file"
if [ "$(kill -l "$?")" = PIPE ]; then
kill -s PIPE "$PPID"
exit
fi
done' sh {} + | head -n 5
Muy ineficiente ya que ejecuta varios comandos para cada archivo.
Relacionado:Ubuntu:¿cómo bloquear la velocidad del ventilador para amd gpu en Ubuntu 20.04?