Comment détecter si "trouver" a trouvé des correspondances?

16

Existe-t-il un moyen idiomatique pour détecter si "trouver" a trouvé des correspondances? J'utilise actuellement

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

mais cela me semble un peu indirect. De plus, j'aimerais que la recherche s'arrête une fois qu'elle a trouvé une correspondance, afin de ne pas perdre de temps et d'efforts. J'ai juste besoin de savoir s'il existe des fichiers qui correspondent.

Mise à jour: j'ai fait l'erreur d'écrire ma question sans le code devant moi: j'utilise wc -ldans un cas différent, où j'ai besoin de connaître le nombre total de fichiers trouvés de toute façon. Dans le cas où je teste uniquement s'il y a des correspondances, j'utilisais if [ -z $(find …) ].

Chris Page
la source

Réponses:

17

Si vous savez que vous avez trouvé GNU, utilisez-le -quit pour l'arrêter après le premier match.

Portable, canalisez la sortie de finddans head -n 1. De cette façon find, un tube cassé mourra après quelques correspondances (quand il est rempli headdu tampon d'entrée).

Quoi qu'il en soit, vous n'avez pas besoin wcde tester si une chaîne est vide, le shell peut le faire seul.

if [ -n "$(find … | head -n 1)" ]; then …
Gilles 'SO- arrête d'être méchant'
la source
Intéressant ... Je pensais -nque cela ne s'appliquait qu'aux variables "définies" ($ abc, $ xyz, etc.), mais je suppose que $ (...) est une variable temporaire "définie" .. +1 ... (et je viens lisez récemment que l'utilisation -nest risquée, sauf si vous êtes sûr que la variable n'a pas déjà été déclarée et qu'elle est 'inutilisée) ... mais un temp n'aura pas cette possibilité ... ie. non initialisé vs vide
Peter.O
2
@fred: Au contraire, -nteste si une chaîne est vide, elle n'a rien à voir avec les variables. Ce que vous avez lu disait probablement que l'utilisation -nne teste pas si une variable est définie: -n "$foo"est fausse si fooest définie mais vide et affiche un message d'erreur sous set -u. [ -n "${foo+1}" ]teste de manière fiable s'il fooest défini, mais le traitement identique des variables vides et non définies est généralement une bonne idée:, [ -n "${foo:+1}" ]ou tout simplement [ -n "$foo" ]si cela ne vous inquiète pas set -u.
Gilles 'SO- arrête d'être méchant'
Merci! Je n'ai pas -quitdisponible, mais la tuyauterie head -n 1fonctionne (comme le fait head -c 1, qui s'arrête encore plus tôt, mais probablement avec un avantage négligeable). De plus, j'ai fait l'erreur d'écrire ma question sans le code devant moi: j'utilise wc -ldans un cas différent, où j'ai besoin de connaître le nombre total de fichiers trouvés. Dans le cas où je teste uniquement s'il y a des correspondances, j'utilisais if [ -z `find … ` ].
Chris Page
6

Vous pouvez utiliser l' -quitaction pour arrêter après le premier match. Vous voudrez probablement combiner cela avec une autre action (comme -print) ou vous ne pourrez pas dire s'il a trouvé quelque chose.

Par exemple, find ... -print -quitimprime le chemin du premier fichier correspondant, puis quitte. Ou, vous pouvez utiliser -printf 1 -quitpour imprimer 1 s'il y a une correspondance et rien s'il n'y en a pas.

findLe statut de sortie de '' reflète s'il y a eu des erreurs lors de la recherche, et non s'il a trouvé quelque chose, vous devez donc vérifier sa sortie pour voir s'il y a une correspondance.

cjm
la source
-quitest une extension GNU. Il ne fonctionnera pas sur les systèmes utilisant d'autres implémentations de find (1), comme OS X, les BSD et probablement la plupart des Unices commerciaux.
Warren Young
Merci, c'est utile de savoir si j'utilise un autre système. Malheureusement, ni -quit ni -printf ne sont disponibles sur le mien (Mac OS X).
Chris Page
4

La sortie 0 est facile avec find, la sortie> 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

Notez que cette solution est plus performante que l'utilisation d'un sous-shell; exécuter faux est certainement plus rapide que d'exécuter même 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
la source
0

Vous pouvez l'envelopper dans l'état de la coque, par exemple:

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

...est votre condition de match, par exemple -name *.txt.

Quelques autres exemples:

[ "$(find /etc -name hosts)" ] && echo True || echo False
[ ! -z "$(find /etc -name hosts)" ] && echo True || echo False
Kenorb
la source