Posso fazer com que o `find` retorne não-0 quando nenhum arquivo correspondente for encontrado?

46

Mesmo quando /tmpnão há um arquivo chamado something, procurá-lo findretornará 0:

  $ find /tmp -name something 
  $ echo $?
  0

Como posso obter um status de saída diferente de zero quando findnão encontra nada?

yael
fonte

Respostas:

44

Aqui está uma frase que acredito que faz o que você quer:

find /tmp -name something | egrep '.*'

O status de retorno será 0quando algo for encontrado e diferente de zero.

Se você também precisar capturar a saída findpara processamento adicional, a resposta de Sven cobriu isso.

Steven segunda-feira
fonte
14
A trilha *no egrepregex é completamente redundante. Como você não está usando egrepsintaxe de expressão regular, a idade antiga greppode ser alguns microssegundos mais rápida.
Tripleee 30/10
eu aprendi a usarfind ... | read
Sam
14

Solução mais simples que não imprime, mas sai 0 quando os resultados são encontrados

find /tmp -name something | grep -q "."
Matt Kneiser
fonte
2
As aspas duplas não servem para nada aqui.
haridsv 10/04
Enquanto as aspas duplas não servem para nenhuma função de código, elas tornam mais claro para o leitor que o caractere de ponto final é uma regex e não um diretório.
Dharma Bellamkonda
13

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
Steven Penny
fonte
2
Até onde eu sei, isso não funciona. O código de saída de findnão parece depender dos códigos de saída de nenhum -execs executado.
22417 Chris
@ Chris trabalha para mim, e os 4 que upvoted
Steven Penny
exemplo para resultado incorretamente falso desta solução: find / existente-ponto-de-partida / não-existente-ponto-de-partida-name arquivo-in-existente-ponto-de-partida -exec false {} +
Gerald Schade
2
Isso funciona corretamente e está documentado (embora oculto na execseção, sem valor de retorno). Ele não consegue diferenciar entre nada encontrado e se vê errando (por exemplo, quando foi chamado em um ponto de partida inexistente).
Tgr 20/04
Se você precisar dessa funcionalidade - sim
Gerald Schade
7

Tendo acabado de encontrar esta pergunta enquanto tentava encontrar minha maneira de resolver um problema com o Puppet (alterar permissões nas pastas em um diretório, mas não no próprio diretório), isso parece funcionar:

! test -z $(find /tmp -name something)

Meu caso de uso específico é este:

! test -z $(find /home -mindepth 1 -maxdepth 1 -perm -711)

O que sairá do código 1 se o comando find não encontrar arquivos com as permissões necessárias.

shearn89
fonte
Algumas soluções (não tentei todas) aqui não funcionavam em um Mac; isso fez.
Alex Hall
5

Não é possível. Find retorna 0 se sair com êxito, mesmo que não tenha encontrado um arquivo (que é um resultado correto, não indicando um erro quando o arquivo realmente não existe).

Para citar a página de manual de localização

ESTADO DE SAÍDA

encontre saídas com status 0 se todos os arquivos forem processados ​​com êxito, maior que 0 se ocorrerem erros. Esta é uma descrição deliberadamente muito ampla, mas se o valor de retorno for diferente de zero, você não deve confiar na exatidão dos resultados da localização.

Dependendo do que você deseja alcançar, você pode tentar encontrar -printo nome do arquivo e testar a saída:

#!/bin/bash
MYVAR=`find . -name "something" -print`
if [ -z "$MYVAR" ]; then
    echo "Notfound"
else
   echo $MYVAR
fi
Sven
fonte
Certamente é possível , embora não seja tão robusto quanto se poderia querer.
Ruslan
A página do manual está mal organizada; o que Ruslan disse está documentado na opção exec/ execdir(usada com +):If any invocation returns a non-zero value as exit status, then find returns a non-zero exit status.
Tgr
1

Eu sinto que este é o método mais conciso e direto:

test `find /tmp/ -name something -print -quit 2>/dev/null`
danorton
fonte
2
Nesse caso, se encontrar um erro, imprimirá o resultado em / dev / null, retornará uma saída diferente de zero e, em seguida, a fixará em 0 pelo comando test.
Jeff Ferland
Não acredito que seja verdade. Por favor, descreva seu exemplo. Se houver um erro e encontrar saídas, a sequência estará vazia e o teste retornará diferente de zero.
Danorton
Não sei ao certo qual é o seu exemplo, mas omiti-o acidentalmente -print -quit, o que pode resolver sua preocupação.
Danorton
Talvez a outra pessoa que tenha votado mal (provavelmente pelo mesmo motivo) possa fornecer um exemplo contrário?
Danorton
1
Ok, você simplesmente não gosta do meu estilo. Para os meus casos de uso, quaisquer erros encontrados podem relatar um ruído ou são tão graves que aparecerão em outro lugar. De qualquer forma, esse método responde corretamente à pergunta final: "Existe um arquivo acessível no caminho com o nome fornecido". Um erro retornará uma resposta correta de "Não". Se eu quiser descobrir por que não, posso adicionar um código mais complexo que responda a perguntas que não foram originalmente colocadas aqui.
Danorton
0

Aqui está um pequeno script que eu chamei test.py. Ele aprimora os outros métodos publicados, na medida em que retornará um código de erro se um estiver definido e, adicionalmente, um se encontrar não listou nenhum arquivo:

from subprocess import Popen
import sys

p = Popen(['find'] + sys.argv)
out, err = p.communicate()
if p.returncode:
    sys.exit(p.returncode)
if not out:
    sys.exit(1)

Aqui está a saída da linha de comando:

$ python test.py . -maxdepth 1 -name notthere
$ echo $?
1
$ find . -maxdepth 1 -name notthere
$ echo $?
0
$ find . -failedarg
find: unknown predicate `-failedarg'
$ echo $?
1

Em seguida, para um resultado em que find teve erros, mas encontrou arquivos:

$ ls -lh
$ d---------  2 jeff users   6 Feb  6 11:49 noentry
$ find .
.
./noentry
find: `./noentry': Permission denied
$ echo $?
1
$ find . | egrep '.*'
.
./noentry
find: `./noentry': Permission denied
$ echo $?
0
python ../test.py 
../test.py
$ echo $?
1

Então, se você quiser a lista de arquivos, poderá -print 0passar finde dividir a variável out em valores nulos ou simplesmente adicionar uma instrução de impressão para ela.

Jeff Ferland
fonte
-1

Não é apenas findisso que retorna os códigos de status de saída como zero quando é bem-sucedido. No unix, seja qual for o comando que você executa, se for bem-sucedido, ele retornará o status de saída como zero.

Informatica-Oracle-Unix
fonte