Wie kann festgestellt werden, ob "find" Übereinstimmungen gefunden hat?

16

Gibt es ein idiomatisches Mittel, um festzustellen, ob "find" Übereinstimmungen gefunden hat? Ich benutze gerade

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

aber das scheint mir ein wenig indirekt zu sein. Außerdem möchte ich, dass find aufhört zu suchen, sobald es eine Übereinstimmung gefunden hat, damit es keine Zeit und Mühe verschwendet. Ich muss nur wissen, ob Dateien vorhanden sind, die übereinstimmen.

Update: Ich habe den Fehler gemacht, meine Frage ohne den Code vor mir zu schreiben: Ich verwende wc -lin einem anderen Fall, in dem ich die Gesamtzahl der gefundenen Dateien ohnehin kennen muss. In dem Fall, in dem ich nur prüfe, ob Übereinstimmungen vorhanden sind, habe ich verwendet if [ -z $(find …) ].

Chris Page
quelle

Antworten:

17

Wenn Sie wissen, dass Sie GNU find haben, verwenden Sie -quit , um es nach dem ersten Match anzuhalten.

Portabel, leiten Sie die Ausgabe von findin head -n 1. Auf diese Weise findstirbt die Pfeife nach einigen Übereinstimmungen (wenn der headEingabepuffer gefüllt ist ).

In beiden Fällen müssen Sie nicht wctesten, ob eine Zeichenfolge leer ist. Die Shell kann dies alleine tun.

if [ -n "$(find … | head -n 1)" ]; then …
Gilles 'SO - hör auf böse zu sein'
quelle
Interessant ... Ich dachte, es galt -nnur für 'definierte' Variablen ($ abc, $ xyz usw.), aber ich nehme an, dass $ (...) eine 'definierte' temporäre Variable ist. +1 ... (und ich nur Lesen Sie kürzlich, dass die Verwendung von -nriskant ist, es sei denn, Sie sind sich sicher, dass die Variable noch nicht deklariert wurde und nicht verwendet wird. uninitialized vs. empty
Peter.O
2
@fred: Testet im Gegenteil, -nob eine Zeichenkette leer ist, es hat nichts mit Variablen zu tun. Was Sie gelesen haben, war wahrscheinlich, dass die Verwendung -nnicht testet, ob eine Variable definiert ist: -n "$foo"ist falsch, wenn foodefiniert, aber leer, und zeigt eine Fehlermeldung unter set -u. [ -n "${foo+1}" ]testet zuverlässig, ob foogesetzt, aber leere und nicht gesetzte Variablen identisch zu behandeln, ist normalerweise eine gute Idee: [ -n "${foo:+1}" ]oder nur, [ -n "$foo" ]wenn Sie sich keine Sorgen machen set -u.
Gilles 'SO- hör auf böse zu sein'
Vielen Dank! Ich habe nicht -quitverfügbar, aber Piping-to- head -n 1Works (wie auch head -c 1, was noch früher aufhört, aber wahrscheinlich mit vernachlässigbarem Nutzen). Außerdem habe ich den Fehler gemacht, meine Frage ohne den Code vor mir zu schreiben: Ich verwende wc -lin einem anderen Fall, in dem ich die Gesamtzahl der gefundenen Dateien kennen muss. In dem Fall, in dem ich nur prüfe, ob Übereinstimmungen vorhanden sind, habe ich verwendet if [ -z `find … ` ].
Chris Seite
6

Mit der -quitAktion können Sie nach dem ersten Spiel anhalten. Sie werden das wahrscheinlich mit einer anderen Aktion (wie -print) kombinieren wollen oder Sie werden nicht in der Lage sein zu sagen, ob sie etwas gefunden hat.

Zum Beispiel find ... -print -quitwird der Pfad der ersten übereinstimmenden Datei gedruckt und dann beendet. Oder Sie können -printf 1 -quit1 drucken, wenn es eine Übereinstimmung gibt, und nichts, wenn es keine gibt.

findDer Beendigungsstatus gibt an, ob bei der Suche Fehler aufgetreten sind und nicht, ob etwas gefunden wurde. Sie müssen daher die Ausgabe überprüfen, um festzustellen, ob eine Übereinstimmung vorliegt.

cjm
quelle
-quitist eine GNU-Erweiterung. Es funktioniert nicht auf Systemen, die andere Implementierungen von find (1) verwenden, z. B. OS X, BSDs und wahrscheinlich die meisten kommerziellen Unices.
Warren Young
Danke, das ist nützlich, um zu wissen, ob ich ein anderes System verwende. Leider sind unter mir weder -quit noch -printf verfügbar (Mac OS X).
Chris Seite
4

Exit 0 ist mit find einfach, Exit> 0 ist schwieriger, weil das normalerweise nur mit einem Fehler passiert. Wie auch immer, wir können es schaffen:

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

Beachten Sie, dass diese Lösung leistungsfähiger ist als die Verwendung einer Subshell. false auszuführen ist sicherlich schneller als sogar Dash auszuführen:

$ 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
quelle
0

Sie können es in den Shell-Zustand einwickeln, zB:

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

Wo ...ist Ihre Matchbedingung, z -name *.txt.

Einige andere Beispiele:

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