Puis-je faire en sorte que `find` renvoie non-0 quand aucun fichier correspondant n'est trouvé?

46

Même quand /tmpaucun fichier n'a été appelé something, la recherche avec findretournera 0:

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

Comment puis-je obtenir un statut de sortie non nul quand findne trouve rien?

yael
la source

Réponses:

44

Voici une ligne qui, je crois, fait ce que vous voulez:

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

L'état de retour sera 0quand quelque chose est trouvé et différent de zéro sinon.

Si vous devez également capturer la sortie de findpour un traitement ultérieur, alors la réponse de Sven a couvert cela.

Steven Monday
la source
14
La fin *sur la egrepregex est complètement redondante. Puisque vous n'utilisez pas egrepla syntaxe d'expression régulière, cela greppeut prendre quelques microsecondes plus rapidement.
triple-
J'ai appris à utiliserfind ... | read
Sam
14

La solution la plus simple qui n'imprime pas, mais quitte 0 lorsque les résultats sont trouvés

find /tmp -name something | grep -q "."
Matt Kneiser
la source
2
Les guillemets ne servent à rien ici.
haridsv
Bien que les guillemets doubles ne servent à aucune fonction de code, ils indiquent clairement au lecteur que le caractère point est une regex et non un répertoire.
Dharma Bellamkonda
13

La sortie 0 est facile avec find, exit> 0 est plus difficile car cela ne se produit généralement qu'avec une erreur. Cependant, nous pouvons y arriver:

if find -type f -exec false {} +
then
  echo 'nothing found'
else
  echo 'something found'
fi
Steven Penny
la source
2
Autant que je sache, cela ne fonctionne pas. Le code de sortie de findne semble pas dépendre des codes de sortie des programmes -execqu’il a exécutés.
Chris
@Chris travaille pour moi et les 4 qui ont voté
Steven Penny
exemple pour résultat faussement faux de cette solution: recherche / point de départ existant / point de départ non existant nom de fichier dans le point de départ existant -exec false {} +
Gerald Schade
2
Cela fonctionne correctement et est documenté (bien que caché dans la execsection, pas sous la valeur de retour). Il ne peut pas différencier rien trouvé et se trouver en erreur (par exemple, quand il a été invoqué sur un point de départ inexistant).
Tgr
Si vous avez besoin de cette fonctionnalité - oui
Gerald Schade
7

Ayant trouvé cette question tout en essayant de trouver un moyen de résoudre un problème avec Puppet (modifier les autorisations sur les dossiers situés dans un répertoire mais pas sur le répertoire lui-même), cela semble fonctionner:

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

Mon cas d'utilisation spécifique est le suivant:

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

Ce qui quittera le code 1 si la commande find ne trouve aucun fichier avec les autorisations requises.

shearn89
la source
Quelques solutions (ne les ont pas toutes essayées) ici ne fonctionnaient pas sur un Mac; cela a fait.
Alex Hall le
5

Ce n'est pas possible. Find renvoie 0 s'il réussit, même s'il n'a pas trouvé de fichier (résultat correct n'indiquant pas d'erreur lorsque le fichier n'existe pas).

Pour citer la page de manuel de recherche

STATUS DE SORTIE

trouver les exits avec le statut 0 si tous les fichiers sont traités avec succès, supérieur à 0 si des erreurs se produisent. C'est délibérément une description très large, mais si la valeur de retour est différente de zéro, vous ne devez pas vous fier à l'exactitude des résultats de find.

Selon ce que vous souhaitez réaliser, vous pouvez essayer de trouver -printle nom du fichier et de le tester par rapport à sa sortie:

#!/bin/bash
MYVAR=`find . -name "something" -print`
if [ -z "$MYVAR" ]; then
    echo "Notfound"
else
   echo $MYVAR
fi
Sven
la source
C'est certainement possible , mais pas aussi robuste qu'on pourrait le souhaiter.
Ruslan
La page de manuel est mal organisée; ce que Ruslan a dit est documenté sous l’ option exec/ execdir(utilisé avec +):If any invocation returns a non-zero value as exit status, then find returns a non-zero exit status.
Tgr
1

Je pense que c'est la méthode la plus concise et la plus directe:

test `find /tmp/ -name something -print -quit 2>/dev/null`
Danorton
la source
2
Dans ce cas, si find avait une erreur, il imprimait le résultat dans / dev / null, renvoyait une sortie non nulle et fixait ensuite le résultat à 0 avec la commande test.
Jeff Ferland
Je ne crois pas que ce soit vrai. S'il vous plaît décrire votre exemple. S'il y a une erreur et que vous trouvez des exits, la chaîne sera vide et test renverra une valeur autre que zéro.
danorton
Je ne suis pas sûr de ce que votre exemple pourrait être, mais j'ai accidentellement omis -print -quit, ce qui pourrait répondre à votre préoccupation.
danorton
Peut-être que l’autre personne qui a rétrogradé (probablement pour la même raison) peut donner un exemple contraire?
danorton
1
Ok, tu n'aimes pas mon style. Dans mes cas d'utilisation, les erreurs détectées sont soit du bruit, soit si graves qu'elles seront affichées ailleurs. Dans tous les cas, cette méthode répond correctement à la dernière question: "Y a-t-il un fichier accessible dans le chemin par le nom donné". Une erreur retournera une réponse correcte de "Non". Si je veux savoir pourquoi, je peux ajouter un code plus complexe qui répond aux questions non posées à l'origine.
danorton
0

Voici un petit script que j'ai appelé test.py. Il améliore les autres méthodes publiées en ce sens qu'il renvoie un code d'erreur s'il est défini, et en ajoute un si find ne répertorie aucun fichier:

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)

Voici la sortie en ligne de commande:

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

Ensuite, pour un résultat où find avait des erreurs mais des fichiers trouvés:

$ 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

Ensuite, si vous voulez la liste de fichiers que vous pouvez utiliser, -print 0transmettez findet divisez la variable out sur les valeurs null, ou vous pouvez simplement ajouter une instruction print pour elle.

Jeff Ferland
la source
-1

Ce n'est pas seulement findque renvoie les codes d'état de sortie à zéro lorsqu'il réussit. Sous Unix quelle que soit la commande que vous exécutez, si elle réussit, elle renvoie l'état de sortie à zéro.

Informatica-Oracle-Unix
la source