2012-07-19 24 views
10

Estoy utilizando satisfactoriamente find para crear una lista de todos los archivos en el subdirectorio actual, excluyendo aquellos en el subdirectorio "caché". Aquí está mi primer bit de código:Tubería encuentra resultados en grep para la rápida exclusión de directorio

find . -wholename './cach*' -prune -o -print 

Ahora deseo canalizar esto en un comando grep. Parece que debería ser simple:

find . -wholename './cach*' -prune -o -print | xargs grep -r -R -i "samson" 

... pero esto está devolviendo resultados que son en su mayoría del directorio de caché. He intentado eliminar la referencia de xargs, pero eso hace lo que cabría esperar, ejecutando grep en el texto de los nombres de los archivos, en lugar de en los archivos. Mi objetivo es encontrar "samson" en cualquier archivo que no esté en el contenido almacenado en caché.

Probablemente voy a solucionar este problema simplemente usando grep dobles en este caso, pero tengo mucha curiosidad acerca de por qué este one-liner se comporta de esta manera. Me encantaría escuchar ideas sobre una forma de modificarlo sin dejar de utilizar estos dos comandos (ya que hay ventajas de velocidad para hacerlo de esta manera).

(Esto está en CentOS 5, por cierto.)

Respuesta

9

El wholename partido puede ser la razón por la que todavía está incluyendo archivos "caché". Si está ejecutando el comando find en el directorio que contiene la carpeta "caché", debería funcionar. Si no, intente cambiarlo a -name '*cache*' en su lugar.

Además, no necesita -r o -R para su grep, que le dice que se repita a través de directorios, pero está probando archivos individuales.

Puede actualizar su comando usando la versión corriente, o un solo mando:

find . -name '*cache*' -prune -o -print0 | xargs -0 grep -il "samson" 

o

find . -name '*cache*' -prune -o -exec grep -iq "samson" {} \; -print 

Nota, la -l en el primer comando grep a "enumerar el archivo "y no la (s) línea (s) que coinciden. El -q en el segundo hace lo mismo; le dice a grep que responda silenciosamente para que find imprima el nombre del archivo.

+0

¡Gracias! La eliminación de la recursividad es lo que hizo el truco para mí. (Los viejos hábitos se vuelven difíciles. Por cierto, eso fue un error por mi parte, ya que suelo usar "-r -i -I", lo que tiene mucho más sentido que las banderas de recursividad redundantes). La parte de "nombre completo" estaba bien, ya que el subdirectorio no deseado se encuentra en el nivel raíz del directorio actual. Así que ahora es: 'encontrar. -wholename './cach*' -prune -o -print | xargs grep -i -I "samson" ' – eternalnewb

+0

Impresionante, me alegro de que fuera algo simple =] – newfurniturey

3

Utilice la opción -exec en vez de encontrar a llevarlas por otro comando. Desde allí puede usar grep "samson" {} \; para buscar samson en cada archivo listado.

Por ejemplo:

find . -wholename './cach*' -prune -o -exec grep "samson" "{}" + 
3

Usted ha dicho grep recurse (¡dos veces! -r y -R son sinónimos). Como uno de los argumentos que está pasando es . (el directorio superior), grep está buscando en cada archivo (algunos de ellos dos veces, o incluso más si están en subdirectorios).

Si usted va a utilizar find y grep, hacer esto:

find . -path './cach*' -prune -o -print0 | xargs -0 grep -i "samson" 

Usando -print0 y -0 hace que su script funcione incluso con nombres de archivo que contienen espacios o caracteres de puntuación.

Sin embargo, es probable que no tiene que molestarse con find aquí, ya grep de GNU es capaz de excluir directorios:

grep -R --exclude-dir='cach*' -i "samson" . 

(Esto también excluye ./deeply/nested/directory/cache Si sólo desea excluir directorios de caché en el. toplevel, use find como lo hizo.)

+0

Si hay demasiados archivos en la carpeta/ruta actual, el único' grep' devolverá un error de "demasiados argumentos", por lo que Tendrás que tener cuidado con eso solo. – newfurniturey

+0

¡Gracias por aprovechar esto! Como se menciona en la respuesta "aceptada", limpiar eso solucionó las cosas de inmediato. Ustedes son geniales. – eternalnewb

+0

@newfurniturey No, un error de "demasiados argumentos" vendría del shell, si la línea de comando fuera demasiado larga (por ejemplo, si hubiera escrito 'grep ... *' y hubiera muchos archivos). Aquí no hay globbing de shell, la línea de comando tiene exactamente 43 caracteres. – Gilles

Cuestiones relacionadas