Estou tentando encontrar todos os arquivos de um determinado tipo e que não contenham uma determinada string. Estou tentando fazer isso canalizando find para grep -v
exemplo:
find -type f -name '*.java' | xargs grep -v "something something"
Isso não parece funcionar. Parece estar apenas retornando todos os arquivos que o comando find encontrou. O que estou tentando fazer é basicamente encontrar todos os arquivos .java que correspondam a um determinado nome de arquivo (por exemplo, termina com 'Pb' como em SessionPb.java) e que não tenham um 'extends SomethingSomething' dentro dele.
Minha suspeita é que estou fazendo errado. Então, como deveria ser o comando?
Responder1
Não há necessidade xargs
aqui. Além disso, você precisa usar a opção grep
with -L
(arquivos sem correspondência), caso contrário, ele exibirá o conteúdo do arquivo em vez de seu nome, como no seu exemplo.
find . -type f -iname "*.java" -exec grep -L "something somethin" {} \+
Responder2
Você quase conseguiu, realmente...
find . -type f -iname "*.java" -print0 | xargs -0 grep -v "something something"
O ponto '.' diz para começar daqui. (o seu implica isso .. mas nunca presuma).
-inameusa pesquisa que não diferencia maiúsculas de minúsculas, apenas por precaução (ou simplesmente sem maiúsculas e minúsculas).
-imprimir0envia nomes de arquivos para xargs com um caractere \x00 final, o que evita problemas com nomes de arquivos contendo espaços.
o '-0' em xargs diz para esperar nomes de arquivos terminando em \x00 em vez de retornos.
e seu comando grep ...
Praticamente entendi.
EDITAR::
Da sua atualização:
find . -type f -iname "*pb.java" -print0 | xargs -0 grep -iL "something"
deveria ajudar. (Adicionado -L da resposta de @rush, bom trabalho)
Tenho a impressão de que o seu grep precisa da opção '-i' ou de ser menos explícito.
Tente o comando em partes... ESTE produz nomes de arquivos que parecem adequados?
find . -type f -iname "*pb.java"
Nesse caso, é provável que seu problema seja que seu padrão de pesquisa grep não corresponda (erro de ortografia? isso acontece!) Ou simplesmente não há correspondências.
Pior caso absoluto:
grep -riL "something" *
fará MUITO mais trabalho pesquisando tudo, mas deverá fornecer alguma saída.
Responder3
O computador está sendo um computador: está fazendo o que você mandou, em vez do que você queria que ele fizesse.
grep -v "something something"
imprime todas as linhas que não contêm something something
. Por exemplo, ele imprime duas linhas entre as três seguintes:
hello world
this is something something
something else
Para imprimir arquivos que não contêm extends SomethingSomething
nenhum lugar, use a -L
opção:
grep -L -E 'extends[[:space:]]+SomethingSomething' FILENAME…
Algumas versões do grep não possuem a -L
opção (não é especificada porPOSIX). Se o seu não imprimir, não imprima nada e use o código de retorno para que o shell de chamada faça o que for necessário.
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 }
'
No Linux ou Cygwin (ou outro sistema com GNU grep), você não precisa usar find
, pois grep
é capaz de ser recursivo.
grep -R --include='*.java' -L -E 'extends[[:space:]]+SomethingSomething'
Se o seu shell for ksh ou bash ou zsh, você pode fazer com que o shell faça a correspondência do nome do arquivo. No bash, execute set -o globstar
primeiro (você pode colocar isso no seu arquivo ~/.bashrc
).
grep -L -E 'extends[[:space:]]+SomethingSomething' **/*.java
Responder4
find -type f -name '*.java' 2>&1 | grep -v "something something"
o que você está "exibindo" é exibido no stderr, não no stdout.
o comando acima redireciona stderr para stdout