Como posso encontrar todos os arquivos que NÃO contêm uma sequência de texto?

40

Que comando conciso posso usar para encontrar todos os arquivos que NÃO contêm uma sequência de texto?

Eu tentei isso (usando -v para inverter os parâmetros do grep) sem sorte:

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

Alguém disse que isso funcionaria:

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

Mas isso não parece funcionar para mim.

Esta página tem este exemplo:

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

Mas isso é complicado e nada conciso.

ps: Eu sei que grep -L *isso é possível, mas como posso usar o comando find em combinação com grep para arquivos excluídos é o que realmente quero saber.

pss: Também não tenho certeza de como o grep deve incluir subdiretórios com a grep -L *sintaxe, mas ainda quero saber como usá-lo com find:)

cwd
fonte
11
O primeiro comando que você escreveu funcionou bem no meu computador. Qual versão do find você está usando? E já que estamos no assunto, talvez especificar quais unix você está correndo ..
rahmu
@rahmu, esse comando quase sempre não funciona como o esperado. Você provavelmente teve um caso muito específico. Por favor, veja unix.stackexchange.com/questions/339619/…
sgnsajgon

Respostas:

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

OU

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

Aqui estamos calculando o número de linhas correspondentes (usando -c) em um arquivo se a contagem for 0, então é o arquivo necessário, então cortamos a primeira coluna, ou seja, o nome do arquivo da saída.

Sachin Divekar
fonte
6
Isso é muito complicado. Veja a resposta de Kevin .
Gilles 'SO- stop be evil'
@ Gilles sim, eu concordo com você. Eu tenho +1 na resposta dele.
Sachin Divekar
6
Isso não é apenas "terrivelmente complicado", mas está errado , pois também listaria todos os arquivos que contêm um múltiplo de 10 linhas correspondentes ao padrão. Mesmo que grepfoi fixado este ainda assumiria nenhum nome de arquivo contendo :ou nova linha caracteres ...
don_crissti
@don_crissti, obrigado por mencionar! Ainda assim, a menos que você use muito código de copiar e colar, a solução acima é um truque interessante.
Ufos
@Ufos - Eu realmente não entendo o seu comentário ... Isso está errado . De qualquer forma, não hesite em usá-lo se ele se parece com um "muito bom chamariz" para você ...
don_crissti
57

Sua descoberta deve funcionar se você alterar -v -l(arquivos com qualquer linha que não corresponda) para -L(arquivos sem linhas correspondentes), mas você também poderá usar grepa -ropção recursive ( ):

grep -rL shared.php .
Kevin
fonte
qual achado deve funcionar?
Cwd
@ Kevin - desculpe, find . -exec grep -v -l shared.php {} \;(e todas as outras variantes que eu tentei) não está funcionando para mim. Estou no OS X, mas não acho que isso importe. Eu te dei um +1 porque tinha esquecido a -ropção.
Cwd
@cwd Eu sei que isso é antigo, mas quero deixar isso aqui para futuros leitores: o fato de você estar no OS X faz diferença. O Mac OSX usa comandos do FreeBSD. A maioria das pessoas aqui assume comandos no estilo Linux (GNU). Eles têm argumentos diferentes, maneiras diferentes de lidar com detalhes.
Ricos Homolka
A partir de 2016 OSX parece suportar-L
David Moles
@ Kevin eu disse que sim, não que não. :) não que alguém tenha explicitamente dito que não, mas os comentários foram confusos (e eu certamente me deparei com outros problemas do OS X / BSD vs GNU).
David Moles
4

Eu sei que isso grep -L *será feito, mas como posso usar o findcomando em combinação com greppara excluir arquivos é o que realmente quero saber

Você pode usar finde grepassim:

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

Aqui -printé executado apenas se a expressão anterior: for ! -exec ... {}avaliada como true.
Portanto, para cada arquivo encontrado, grep -q 'PATTERN'é execusado, se o resultado for false, a expressão inteira será ! -exec grep -q 'PATTERN'avaliada como truee o nome do arquivo será printeditado.

don_crissti
fonte
2
Esse tem o benefício de ser padrão e portátil.
Stéphane Chazelas
Há uma diferença com os GNUs, grep -Lpois também incluirá os arquivos não legíveis na lista.
Stéphane Chazelas
1

Você não encontra resultado correspondente pela opção -L

grep -iL shared.php .
prakash
fonte
-1

Eu acho que você está procurando um comando como

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

A opção -qé grepencerrada e, após o uso, -execdirvocê precisa -printimprimir os arquivos encontrados.

Ronin Tom
fonte