GNU/Linux >> Tutoriales Linux >  >> Linux

¿Limitar la salida de búsqueda y evitar la señal 13?

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?
Linux
  1. Salida a Stdout y al mismo tiempo Grep en un archivo?

  2. ¿Encontrar patrón y mover?

  3. ¿Usar el comando Grep y localizar?

  4. ¿Iptables y proxies transparentes?

  5. Usando grep y sed para encontrar y reemplazar una cadena

Cómo encontrar una cadena o palabra específica en archivos y directorios

Buscar y copiar archivos

Encontrar archivos ejecutables usando ls y grep

Buscar y cambiar el nombre de un directorio

¿Cómo combinar find y grep para una búsqueda compleja? (GNU/linux, buscar, grep)

¿Cómo limitar la salida de ls para mostrar solo el nombre del archivo, la fecha y el tamaño?