Como localizo os arquivos no diretório atual que não contêm a palavra foo
(usando grep
)?
Como localizo os arquivos no diretório atual que não contêm a palavra foo
(usando grep
)?
Respostas:
Se o seu grep tiver a opção -L
(ou --files-without-match
):
$ grep -L "foo" *
GREP_OPTIONS='--exclude-dir=.svn --exclude-dir=.git'
: ^)
-rL
vez de -L
para coincidir com subdiretórios
grep -L 'foo' -- *
O padrão é que os comandos que usam opções longas são usadas --
para indicar que não há mais opções após esse ponto.
Dê uma olhada ack
. Ele faz a .svn
exclusão automaticamente, fornece expressões regulares do Perl e é um download simples de um único programa do Perl.
O equivalente ao que você está procurando deve ser ack
:
ack -L foo
Você pode fazer isso apenas com grep (sem encontrar).
grep -riL "foo" .
Esta é a explicação dos parâmetros usados no grep
-L, --files-without-match
each file processed.
-R, -r, --recursive
Recursively search subdirectories listed.
-i, --ignore-case
Perform case insensitive matching.
Se você usar l
(em minúsculas), obterá o oposto (arquivos com correspondências)
-l, --files-with-matches
Only the names of files containing selected lines are written
O comando a seguir fornece todos os arquivos que não contêm o padrão foo
:
find . -not -ipath '.*svn*' -exec grep -H -E -o -c "foo" {} \; | grep 0
grep '0$'
também corresponderia arquivos com múltiplos de 10 linhas! Você precisa grep ':0$'
no final verificar se há um ': 0' explícito no final da linha. Então você receberá apenas arquivos com zero linhas correspondentes.
O comando a seguir exclui a necessidade de a localização filtrar as svn
pastas usando um segundo grep
.
grep -rL "foo" ./* | grep -v "\.svn"
Você realmente precisará de:
find . -not -ipath '.*svn*' -exec grep -H -E -o -c "foo" {} \; | grep :0\$
Problema
Eu preciso refatorar um projeto grande que usa .phtml
arquivos para escrever HTML usando código PHP embutido. Quero usar modelos de bigode . Quero encontrar quaisquer .phtml
giles que não contenham a string, new Mustache
pois eles ainda precisam ser reescritos.
Solução
find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'
Explicação
Antes dos tubos:
Encontrar
find .
Encontre arquivos recursivamente, iniciando neste diretório
-iname '*.phtml'
O nome do arquivo deve conter .phtml
( i
isso não diferencia maiúsculas de minúsculas)
-exec 'grep -H -E -o -c 'new Mustache' {}'
Execute o grep
comando em cada um dos caminhos correspondentes
Grep
-H
Sempre imprima cabeçalhos de nome de arquivo com linhas de saída.
-E
Interprete o padrão como uma expressão regular estendida (ou seja, force o grep a se comportar como egrep).
-o
Imprime apenas a parte correspondente das linhas.
-c
Somente uma contagem de linhas selecionadas é gravada na saída padrão.
Isso fornecerá uma lista de todos os caminhos de arquivo que terminam em .phtml
, com uma contagem do número de vezes que a string new Mustache
ocorre em cada um deles.
$> find . -iname '*.phtml$' -exec 'grep -H -E -o -c 'new Mustache' {}'\;
./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/orders.phtml:1
./app/MyApp/Customer/View/Account/banking.phtml:1
./app/MyApp/Customer/View/Account/applycomplete.phtml:1
./app/MyApp/Customer/View/Account/catalogue.phtml:1
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0
O primeiro canal grep :0$
filtra esta lista para incluir apenas linhas que terminam em :0
:
$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$
./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0
O segundo sed 's/..$//'
canal retira os dois caracteres finais de cada linha, deixando apenas os caminhos do arquivo.
$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'
./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml
./app/MyApp/Customer/View/Account/studio.phtml
./app/MyApp/Customer/View/Account/classadd.phtml
./app/MyApp/Customer/View/Account/orders-trade.phtml
Se você estiver usando o git, ele pesquisará todos os arquivos rastreados:
git grep -L "foo"
e você pode procurar em um subconjunto de arquivos rastreados se você tiver ** o globbing do subdiretório ativado ( shopt -s globstar
em .bashrc, consulte o seguinte ):
git grep -L "foo" -- **/*.cpp
Meu grep não possui nenhuma opção -L. Eu acho uma solução alternativa para conseguir isso.
As idéias são:
faça a diferença entre o arquivo 2 dump com o comando diff.
grep 'foo' *.log | cut -c1-14 | uniq > txt1.txt
grep * *.log | cut -c1-14 | uniq > txt2.txt
diff txt1.txt txt2.txt | grep ">"
diff
entre dois fluxos de saída (acho que você envolve os comandos entre parênteses, e há um colchete angular em algum lugar também), se o seu sistema suportar, o que eu acho é a questão, uma vez que não suportagrep -L
find *20161109* -mtime -2|grep -vwE "(TRIGGER)"
Você pode especificar o filtro em "localizar" e a cadeia de exclusão em "grep -vwE". Use mtime em find se precisar filtrar também o horário modificado.
Conforme comentado por @tukan, há um relatório de bug aberto para a Ag referente ao sinalizador -L
/ --files-without-matches
:
Como há pouco progresso no relatório de erros, a -L
opção mencionada abaixo não deve ser considerada , desde que o erro não tenha sido resolvido. Use abordagens diferentes apresentadas neste tópico. Citando um comentário para o relatório de erros [grifo meu]:
Alguma atualização sobre isso?
-L
ignora completamente as correspondências na primeira linha do arquivo. Parece que, se isso não for corrigido em breve, a bandeira deve ser removida completamente, pois efetivamente não funciona como anunciado .
Como uma alternativa poderosa grep
, você pode usar o The Silver Searcher - Ag :
Uma ferramenta de busca de código semelhante ao ack, com foco na velocidade.
Olhando man ag
, encontramos a opção -L
ou --files-without-matches
:
... OPTIONS ... -L --files-without-matches Only print the names of files that don´t contain matches.
Ou seja, para pesquisar recursivamente os arquivos que não correspondem foo
, no diretório atual:
ag -L foo
Para procurar apenas arquivos atuais no diretório atualfoo
, basta especificar --depth=0
a recursão:
ag -L foo --depth 0
-L
erro - github.com/ggreer/the_silver_searcher/issues/238
grep -irnw "filepath" -ve "pattern"
ou
grep -ve "pattern" < file
O comando acima nos dará o resultado conforme -v encontra o inverso do padrão que está sendo pesquisado
-l
opção para imprimir apenas o nome do arquivo; mas isso ainda imprime os nomes de qualquer arquivo que contenha qualquer linha que não contenha o padrão. Acredito que o OP deseja encontrar os arquivos que não contêm nenhuma linha que contenha o padrão.
O comando a seguir pode ajudá-lo a filtrar as linhas que incluem a substring "foo".
cat file | grep -v "foo"
cat
.