2012-03-05 23:28:16 +0000 2012-03-05 23:28:16 +0000
148
148

¿Cómo ignorar ciertos nombres de archivo utilizando "find"?

Uno de mis comandos BASH favoritos es

find . -name '*.*' -exec grep 'SearchString' {} /dev/null \;

que busca el contenido de todos los archivos en y debajo del directorio actual para la SearchString especificada. Como desarrollador, esto ha sido muy útil a veces.

Debido a mi proyecto actual, y la estructura de mi código base, sin embargo, me gustaría hacer este comando BASH aún más avanzado al no buscar ningún archivo que esté en o por debajo de un directorio que contenga “.svn”, o cualquier archivo que termine con “.html”

La página MAN para find me confundió un poco. Intenté usar -prune, y me dio un comportamiento extraño. En un intento de saltar sólo las páginas .html (para empezar), probé con :

find . -wholename './*.html' -prune -exec grep 'SearchString' {} /dev/null \;

y no obtuve el comportamiento que esperaba. Creo que puedo estar perdiendo el sentido de -prune. ¿Podríais ayudarme?

Gracias

Respuestas (3)

209
209
209
2012-03-06 00:40:37 +0000

Puede utilizar la función de negación (!) de find para no coincidir con archivos con nombres específicos:

find . ! -name '*.html' ! -path '*.svn*' -exec grep 'SearchString' {} /dev/null \;

Así que si el nombre termina en .html o contiene .svn en cualquier parte de la ruta, no coincidirá, y por lo tanto el exec no se ejecutará.

12
12
12
2012-03-06 13:54:15 +0000

He tenido el mismo problema durante mucho tiempo, y hay varias soluciones que pueden ser aplicables en diferentes situaciones:

  • ack-grep es una especie de “grep del desarrollador” que por defecto omite los directorios de control de versiones y los archivos temporales. En la página de man se explica cómo buscar sólo en determinados tipos de archivos y cómo definir su propio . Las opciones propias de
  • grep pueden usarse muy fácilmente para omitir globs de archivos y single directorios (no hay globbing para directorios, desafortunadamente).
  • --exclude debería funcionar, pero las opciones anteriores son probablemente menos molestas a largo plazo.
9
9
9
2012-03-06 03:29:21 +0000

El siguiente comando find sí poda los directorios cuyos nombres contienen .svn, Aunque no desciende al directorio, se imprime el nombre de la ruta podada …(¡-name '*.svn' es la causa!) ..

Puede filtrar los nombres de directorio mediante: grep -d skip que omite silenciosamente tales “nombres de directorio” de entrada.

Con GNU grep, puede usar -H en lugar de /dev/null. Como una pequeña cuestión secundaria: puede ser mucho más rápido que `\;`, por ejemplo, para 1 millón de archivos de una línea, usando `\;` tardó _4m20s_, usando tardó sólo 1.2s.

El siguiente método utiliza xargs en lugar de -exec, y asume que no hay nuevas líneas \n en ninguno de sus nombres de archivo. Tal y como se utiliza aquí, xargs es muy parecido al “ de find.

xargs puede pasar nombres de archivos que contengan espacios consecutivos cambiando el delimitador de entrada a '\n' con la opción -d.

Esto excluye los directorios cuyos nombres contienen .svn y greps sólo los archivos que no terminan con .html.

find . \( -name '*.svn*' -prune -o ! -name '*.html' \) |
   xargs -d '\n' grep -Hd skip 'SearchString'