2009-09-14 14 views
5

¿Existe alguna manera fácil de usar grep (o combinar con otras herramientas estándar de línea de comandos) para obtener una lista de todos los archivos que contienen un patrón pero que no tienen un segundo patrón?¿Cómo usar grep para encontrar todos los archivos que contienen un patrón pero no tienen un segundo?

En mi caso particular yo quiero una lista de todos los archivos que contienen el patrón:

override.*commitProperties 

sin embargo, no contienen:

super.commitProperties 

Estoy en Windows, pero usar cygwin ampliamente. Sé cómo encontrar todos los archivos con el primer patrón O todos los patrones sin el segundo, pero no estoy seguro de cómo combinar esas consultas.

Preferiría las respuestas que son genéricas, ya que tengo la sensación de que muchas otras personas podrían encontrar útil este tipo de consulta. Es bastante fácil para mí tomar una solución genérica y conectar mis valores. Acabo de incluir mi instancia específica para facilitar la explicación.

+0

¿No puede canalizar la primera salida de coincidencia de patrón con la segunda y luego hacer una grep allí para el segundo patrón? – vpram86

+1

No - los patrones pueden estar en diferentes líneas – DVK

+0

@ DVk-Oh !!! :) Olvidé eso. ¡Muchas gracias! – vpram86

Respuesta

10
grep -rl "override.*commitProperties" . | xargs grep -L "super.commitProperties" 

-l imprime los archivos con un partido

-L impresiones de los archivos sin necesidad de un partido

+0

Tanto este como hlovdal funcionan, pero me gusta un poco más porque es más simple. – Herms

+0

Uno puede hacer trampa llamando a "superXcommitProperties" para escapar de la ira del que está haciendo el grep para encontrar el código malvado ;-) –

+0

código malvado? no no. Este es un caso en el que me olvido de agregar la súper llamada a mis anulaciones en un par de lugares, provocando que cosas extrañas sucedan. Ya me he vencido a mí mismo, ahora solo estoy buscando todos los lugares que arruiné para poder arreglarlo. :) – Herms

4

Trate

find . -print0 | xargs -0 grep -l "override.*commitProperties" \ 
| tr '\012' '\000' | xargs -0 grep -L super.commitProperties 

El comando tr convertirá a ASCII saltos de línea nula, por lo que se puede utilizar en el segundo -0 xargs, evitando todos los problemas con los espacios en los nombres de archivos, etc. resultado

prueba:

/tmp/test>more 1 2 3 | cat 
:::::::::::::: 
1 
:::::::::::::: 
override.*commitProperties 
super.commitProperties 
:::::::::::::: 
2 
:::::::::::::: 
override.*commitProperties 
:::::::::::::: 
3 
:::::::::::::: 
hello world 
/tmp/test>find . -print0 | xargs -0 grep -l "override.*commitProperties" | tr '\012' '\000' | xargs -0 grep -L super.commitProperties 
./2 
/tmp/test> 

Como señaló Douglas, Encontrar + xargs puede estar sustituido por grep -r.

+0

Eso es más o menos lo que hubiera sugerido, excepto que hubiera usado rep -r en lugar de encontrar. –

+0

¿Podría agregar algunos detalles sobre lo que está haciendo cada comando? Obtengo el hallazgo y grep, pero ¿qué está haciendo? – Herms

+0

Además, ¿por qué el hallazgo? grep -r maneja la repetición de la ruta y la simplifica. ¿Encuentra que las cosas funcionan mejor de alguna manera? – Herms

2

Utilice una combinación de 2 greps y una comm, de la siguiente manera (los patrones son A y B). Tenga en cuenta que un grep entonado no funcionará ya que los patrones podrían estar en líneas dispares.

$ cat a 
A 
$ cat b 
B 
$ cat ab 
A 
B 

$ grep -l A * > A.only 
$ grep -l B * > B.only 

$ comm -23 A.only B.only 
a 

NOTA: el comando comm imprime las líneas comunes o exclusivas de dos archivos. "-23" imprime líneas exclusivas del primer archivo, lo que suprime los nombres de archivo en el segundo archivo.

+2

Nunca antes se ejecutó el comando comm. Me gustan más las soluciones grep para esta situación, ya que no requiere archivos adicionales que me olvidaré de eliminar, pero me alegro de que hayas publicado esto. Siempre es bueno aprender sobre nuevos comandos. – Herms

+0

Puedo estar equivocado, pero creo que la primera solución (con xargs) ejecutará MUCHOS comandos grep para cada uno de los archivos que encuentre. Si bien no es un problema para la comprobación de archivos de configuración menores, será una gran pérdida de recursos si alguna vez necesita hacer la misma lógica en un conjunto muy grande de archivos mediante el lanzamiento de muchos procesos grep secundarios. – DVK

+0

Ver mi comentario sobre la solución aceptada. No creo que se lanzarán más de 2 greps. – Herms

2

Mi solución es similar a Douglas Leeder de, excepto que yo no uso xargs:

grep -l 'override.*commitProperties' $(grep -L super.commitProperties *.txt) 

grep -L comando producto una lista de archivos que NO contiene el patrón n super.commitProperties, el grep -l comando busca * la anulación. commitProperties patrón de esa lista.

En general, es una forma diferente de despellejar al gato.

+0

No estoy familiarizado con esa sintaxis. ¿Qué está haciendo $()? – Herms

+0

La sintaxis $ (comando) es esencialmente la sintaxis de la comilla inversa: 'comando'. El shell reemplaza $ (comando) o 'comando)' con su salida. Puede google "sustitución de comando bash" para más información –

1

ack -l --make "override.*commitProperties" | xargs ack -L "super.commitProperties"

He utilizado este hilo y estaba tratando de hacer una búsqueda recurrente.Tardaría unos 25 minutos +, por lo que averiguó acerca de ack. Lo hice en 5 minutos.

Herramienta útil ack.

0
grep "override.*commitProperties" *| grep -v "super.commitProperties" | cut -d":" -f1 
Cuestiones relacionadas