¿Cómo puedo encontrar todos los archivos que NO contienen una cadena de texto?

40

¿Qué comando conciso puedo usar para encontrar todos los archivos que NO contienen una cadena de texto?

Intenté esto (usando -v para invertir los parámetros de grep) sin suerte:

find . -exec grep -v -l shared.php {} \;

Alguien dijo que esto funcionaría:

find . ! -exec grep -l shared.php {} \;

Pero no parece funcionar para mí.

Esta página tiene este ejemplo:

find ./logs -size +1c  > t._tmp
while read filename
do
     grep -q "Process Complete" $filename
     if [ $? -ne 0 ] ; then
             echo $filename
     fi
done < t._tmp
rm -f t_tmp

Pero eso es engorroso y nada conciso.

ps: sé que grep -L *esto hará esto, pero cómo puedo usar el comando find en combinación con grep para archivos excluidos es lo que realmente quiero saber.

pss: Tampoco estoy seguro de cómo incluir grep subdirectorios con la grep -L *sintaxis, pero todavía quiero saber cómo usarlo con find:)

cwd
fuente
1
El primer comando que escribiste funcionó bien en mi computadora. ¿Qué versión de find estás usando? Y ya que estamos en ello, tal vez especificar qué se está ejecutando Unix ..
rahmu
@rahmu, este comando casi siempre no funciona como espera. Probablemente haya tenido un caso muy específico. Consulte unix.stackexchange.com/questions/339619/…
sgnsajgon

Respuestas:

8
find . -type f | xargs grep -H -c 'shared.php' | grep 0$ | cut -d':' -f1    

O

find . -type f -exec grep -H -c 'shared.php' {} \; | grep 0$ | cut -d':' -f1

Aquí estamos calculando el número de líneas coincidentes (usando -c) en un archivo si el recuento es 0, entonces es el archivo requerido, por lo que cortamos la primera columna, es decir, el nombre de archivo de la salida.

Sachin Divekar
fuente
66
Esto es terriblemente complicado. Ver la respuesta de Kevin .
Gilles 'SO- deja de ser malvado'
@ Gilles sí, estoy de acuerdo contigo. Tengo +1 su respuesta.
Sachin Divekar
66
Esto no solo es "terriblemente complicado", sino incorrecto, ya que también enumeraría todos los archivos que contienen un múltiplo de 10 líneas que coinciden con el patrón. Incluso si eso grepse fijó esto seguiría suponer ningún nombre de archivo que contienen :o de nueva línea caracteres ...
don_crissti
@don_crissti, ¡gracias por mencionarlo! Aún así, a menos que use mucho código de copiar y pegar, la solución anterior es un buen truco.
Ovnis
@Ufos - Realmente no recibo tu comentario ... Esto está mal . De todos modos, siéntase libre de usarlo si le parece un "truco realmente agradable" ...
don_crissti
58

Su hallazgo debería funcionar si cambia -v -l(archivos que no tienen una línea que coincida) a -L(archivos sin líneas que coinciden), pero también podría usar grepla -ropción recursive ( ):

grep -rL shared.php .
Kevin
fuente
¿Qué hallazgo debería funcionar?
cwd
@ Kevin - lo siento, find . -exec grep -v -l shared.php {} \;(y todas las otras variantes que probé) no me funcionan. Estoy en OS X pero no creo que eso deba importar. Te di un +1 porque me había olvidado de la -ropción.
cwd
@cwd Sé que esto es antiguo, pero quiero dejarlo aquí para futuros lectores: el hecho de que estés en OS X marca la diferencia. Mac OSX usa comandos de FreeBSD. La mayoría de las personas aquí asumen comandos de estilo Linux (GNU). Tienen diferentes argumentos, diferentes formas de manejar los detalles.
Rich Homolka
A partir de 2016 OSX parece admitir-L
David Moles
@kevin Dije que sí, no es que no lo haga. :) no es que alguien dijera explícitamente que no, pero los comentarios fueron confusos (y ciertamente me he encontrado con otros problemas de OS X / BSD vs GNU).
David Moles
4

Sé que grep -L *esto hará esto, pero cómo puedo usar el findcomando en combinación con greppara excluir archivos es lo que realmente quiero saber

Podrías usar findy grepasí:

find . -type f ! -exec grep -q 'PATTERN' {} \; -print

Aquí -printse ejecuta solo si la expresión anterior: se ! -exec ... {}evalúa como true.
Entonces, para cada archivo encontrado, grep -q 'PATTERN'se execusa, si el resultado es falseentonces, toda la expresión se ! -exec grep -q 'PATTERN'evalúa como truey se edita el nombre del archivo print.

don_crissti
fuente
2
Ese tiene el beneficio de ser estándar y portátil.
Stéphane Chazelas
Sin grep -Lembargo, hay una diferencia con los GNU en que también incluirá los archivos no legibles en la lista.
Stéphane Chazelas
1

Usted encuentra resultados no coincidentes por la opción -L

grep -iL shared.php .
prakash
fuente
-1

Creo que estás buscando un comando como

find . -type f -execdir grep -q -v shared.php {} \; -print

La opción -qhace grepsalir y después de usar -execdirnecesita -printimprimir los archivos encontrados.

Ronin Tom
fuente