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?