Como detectar se "encontrar" encontrou alguma correspondência?

16

Existe um meio idiomático para detectar se "encontrar" encontrou alguma correspondência? Atualmente estou usando

COUNT=`find ... | wc -l`
if [ "$COUNT" -gt 0 ]; then

mas isso parece um pouco indireto para mim. Além disso, gostaria de parar de pesquisar quando encontrar uma correspondência, para não perder tempo e esforço. Eu só preciso saber se existem ou não arquivos correspondentes.

Atualização: cometi o erro de escrever minha pergunta sem o código à minha frente: uso wc -lem um caso diferente, onde preciso saber o número total de arquivos encontrados de qualquer maneira. No caso em que estou testando apenas se há alguma correspondência, eu estava usando if [ -z $(find …) ].

Chris Page
fonte

Respostas:

17

Se você sabe que o GNU encontra, use -quit para fazê-lo parar após a primeira partida.

Portably, canalize a saída para finddentro head -n 1. Dessa forma find, morrerá um cano quebrado após algumas correspondências (quando o headbuffer de entrada estiver cheio ).

De qualquer forma, você não precisa wctestar se uma string está vazia, o shell pode fazer isso por conta própria.

if [ -n "$(find … | head -n 1)" ]; then …
Gilles 'SO- parar de ser mau'
fonte
Interessante ... Eu pensei que -nsó se aplicava a variáveis ​​'definidas' ($ abc, $ xyz, etc), mas suponho que $ (...) seja uma variável temporária 'definida' .. +1 ... (e eu apenas leia recentemente que o uso -né arriscado, a menos que você tenha certeza de que a variável ainda não foi declarada e não está sendo usada) ... mas uma temperatura não terá essa possibilidade ... ou seja. vs não inicializada esvaziar
Peter.O
2
@fred: Pelo contrário, -ntesta se uma string está vazia, não tem nada a ver com variáveis. O que você leu provavelmente estava dizendo que o uso -nnão testa se uma variável está definida: -n "$foo"é false se fooestá definido, mas está vazio e exibe uma mensagem de erro em set -u. [ -n "${foo+1}" ]testa de forma confiável se fooestá definido, mas tratar variáveis ​​vazias e não definidas de maneira idêntica geralmente é uma boa idéia: [ -n "${foo:+1}" ]ou apenas [ -n "$foo" ]se você não estiver preocupado set -u.
Gilles 'SO- stop be evil'
Obrigado! Eu não tenho -quitdisponível, mas estou indo para o head -n 1trabalho (como faz head -c 1, que para ainda mais cedo, mas provavelmente com benefícios insignificantes). Além disso, cometi o erro de escrever minha pergunta sem o código à minha frente: uso wc -lem outro caso, em que preciso saber o número total de arquivos encontrados. No caso em que estou testando apenas se há alguma correspondência, eu estava usando if [ -z `find … ` ].
Chris Página
6

Você pode usar a -quitação para parar após a primeira partida. Você provavelmente desejará combinar isso com outra ação (como -print) ou não poderá saber se encontrou alguma coisa.

Por exemplo, find ... -print -quitimprimirá o caminho do primeiro arquivo correspondente e sairá. Ou então, você pode -printf 1 -quitimprimir 1 se houver uma correspondência e nada se não houver.

findO status de saída de reflete se houve erros durante a pesquisa e não se encontrou alguma coisa; portanto, você deve verificar sua saída para ver se há uma correspondência.

cjm
fonte
-quité uma extensão GNU. Ele não funcionará em sistemas que usam outras implementações do find (1), como OS X, BSDs e provavelmente a maioria dos Unices comerciais.
Warren Young
Obrigado, é útil saber se estou usando outro sistema. Infelizmente, nem -quit nem -printf estão disponíveis no meu (Mac OS X).
Chris Page
4

A saída 0 é fácil com a localização, a saída> 0 é mais difícil porque isso geralmente acontece apenas com um erro. No entanto, podemos fazer isso acontecer:

if find -type f -exec false {} +
then
  echo 'nothing found'
else
  echo 'something found'
fi

Observe que esta solução é mais eficiente do que usar um subshell; executar false é certamente mais rápido do que executar até o Dash:

$ cat alfa.sh bravo.sh charlie.sh delta.sh
find -name non-existing-file -exec false {} +
find -name existing-file -exec false {} +
[ "$(find -name non-existing-file)" ]
[ "$(find -name existing-file)" ]

$ strace dash alfa.sh | wc -l
807

$ strace dash bravo.sh | wc -l
1141

$ strace dash charlie.sh | wc -l
1184

$ strace dash delta.sh | wc -l
1194
Steven Penny
fonte
0

Você pode envolvê-lo na condição de shell, por exemplo:

[ "$(find . ...)" '!=' '' ] && echo Found || echo Not found

Onde ...está sua condição de correspondência, por exemplo -name *.txt.

Alguns outros exemplos:

[ "$(find /etc -name hosts)" ] && echo True || echo False
[ ! -z "$(find /etc -name hosts)" ] && echo True || echo False
kenorb
fonte