Estoy tratando de encontrar todos los archivos que sean de un tipo determinado y que no contengan una cadena determinada. Estoy tratando de hacerlo canalizando find a grep -v
ejemplo:
find -type f -name '*.java' | xargs grep -v "something something"
Parece que esto no funciona. Parece estar devolviendo todos los archivos que encontró el comando de búsqueda. Lo que estoy tratando de hacer es básicamente encontrar todos los archivos .java que coincidan con un determinado nombre de archivo (por ejemplo, termine con 'Pb' como en SessionPb.java) y que no tengan un 'extiende AlgoAlgo' dentro.
Mi sospecha es que lo estoy haciendo mal. Entonces, ¿cómo debería verse el comando?
Respuesta1
No hay necesidad xargs
aquí. También debe usar la opción grep
with -L
(archivos sin coincidencia), porque de lo contrario generará el contenido del archivo en lugar de su nombre, como en su ejemplo.
find . -type f -iname "*.java" -exec grep -L "something somethin" {} \+
Respuesta2
Ya casi lo tienes realmente...
find . -type f -iname "*.java" -print0 | xargs -0 grep -v "something something"
El punto '.' dice empezar desde aquí. (el tuyo lo implica... pero nunca asumas).
-inameutiliza una búsqueda que no distingue entre mayúsculas y minúsculas, por si acaso (o simplemente sin mayúsculas y minúsculas).
-imprimir0envía nombres de archivos a xargs con un carácter final \x00, lo que evita problemas con los nombres de archivos que tienen espacios.
el '-0' en xargs dice que se esperan nombres de archivos que terminen en \x00 en lugar de devoluciones.
y tu comando grep...
Prácticamente lo entendí.
EDITAR::
De tu actualización:
find . -type f -iname "*pb.java" -print0 | xargs -0 grep -iL "something"
debería ayudar. (Se agregó -L de la respuesta de @rush, buen trabajo)
Tengo la idea de que su grep necesita la opción '-i' o ser menos explícito.
Pruebe el comando en partes... ¿ESTOS nombres de archivos de salida parecen adecuados?
find . -type f -iname "*pb.java"
Si es así, entonces su problema probablemente sea que su patrón de búsqueda grep no coincide (¿error de ortografía? ¡Sucede!), o simplemente no hay coincidencias.
El peor caso absoluto:
grep -riL "something" *
Hará MUCHO más trabajo buscando todo, pero debería brindarle algunos resultados.
Respuesta3
La computadora es una computadora: hace lo que le dijiste que hiciera en lugar de lo que tú querías que hiciera.
grep -v "something something"
imprime todas las líneas que no contienen something something
. Por ejemplo, imprime dos líneas entre las tres siguientes:
hello world
this is something something
something else
Para imprimir archivos que no contienen extends SomethingSomething
ningún lugar, use la -L
opción:
grep -L -E 'extends[[:space:]]+SomethingSomething' FILENAME…
Algunas versiones de grep no tienen la -L
opción (no está especificada porPOSIX). Si el suyo no lo hace, haga que no imprima nada y use el código de retorno para que el shell que llama haga lo que debe hacer en su lugar.
grep -q -E 'extends[[:space:]]+SomethingSomething' FILENAME ||
echo "$FILENAME"
Alternativamente, use awk.
awk '
FNR == 1 && NR != 1 && !found { print fn }
FNR == 1 { fn = FILENAME; found = 0; }
/extends[[:space:]]+SomethingSomething/ { found = 1 }
END { if (fn != "" && !found) print fn }
'
En Linux o Cygwin (u otro sistema con GNU grep), no es necesario utilizar find
, ya grep
que es capaz de recurrir.
grep -R --include='*.java' -L -E 'extends[[:space:]]+SomethingSomething'
Si su shell es ksh, bash o zsh, puede hacer que el shell coincida con el nombre del archivo. En bash, ejecuta set -o globstar
primero (puedes poner esto en tu ~/.bashrc
).
grep -L -E 'extends[[:space:]]+SomethingSomething' **/*.java
Respuesta4
find -type f -name '*.java' 2>&1 | grep -v "something something"
lo que está "obteniendo" se muestra en stderr, no en stdout.
el comando anterior redirige stderr a stdout