Die unerklärlichen Mysterien des find Befehls?

C

Crazy-X

Grünschnabel
Hi,

Der Betreff erklärt mein Problem eigentlich mehr als deutlich: Ich krieg' den find Befehl nicht auf die Reihe. Ich mein, welchen Stoff haben die Entiwckler davon denn gekifft, als sie das verbrochen haben? Logisch konsequent und inutuitiv ist die Bedinung von find jedenfalls nicht:

Also ich habe mal zu Testzwecken ein paar Dateien (und Verzeichnisse) im System verteilt, die alle dem User "lionel" gehören:

Code:
me@zombie $ find / -xdev -user lionel
/etc/fnord
/etc/fnord2
/mnt/blablub
/usr/src/lionel_test
/usr/fnord
/usr/lionel_test2
/usr/dir_lionel
/usr/dir_lionel/blablub

Jetzt möchte ich bei der Suche aber bestimmte Verzeichnisse ausschließen können. Kurz ge'google't und man findet folgende Lösung, aber scheinbar nirgendwo eine gute Erklärung dazu:

Code:
me@zombie $ find / -xdev -path /etc -prune -or -user lionel
/etc
/mnt/blablub
/usr/src/lionel_test
/usr/fnord
/usr/lionel_test2
/usr/dir_lionel
/usr/dir_lionel/blablub

Also einen Blick in "man find", was allerdings nicht den erhofften "Aha-Effekt" bringt sonder nur noch mehr verwirrung stiftet:

man find schrieb:
-prune If -depth is not given, true; do not descend the current directory. If -depth is given, false; no effect.

Wieso hat "-prune" einen boolschen Wert und was zum Teufel hat das mit "-depth" zu tun?? Nach langem Überlegen habe ich mir das jetzt mal so erklärt:

"-path /etc" = A
"-prune" = B
"-user lionel" = C

Boolsche Gleichung:
A ^ B v C ( A UND B ODER C)

Falls A = 0 ist (das Verzeichnis ist nicht /etc), braucht der Ausdruck B nicht untersucht zu werden, da das Ergebnis von A ^ B bereits bekannt ist. Da aber noch ein Oder-Zweig existiert, der die ganze Gleichung noch wahr machen kann, wird der Ausdruck C ausgewertet.
Falls das Verzeichnis aber "/etc" enthält (A = 1) MUSS B ausgewertet werden, um das Ergebnis von A ^ B bestimmen zu können. Und wenn er auf "-prune" trifft, lässt er das Verzeichnis aus. (Und da der erste Teil der Oder Gleichung dann wahr ist, muss C nicht mehr ausgewertet werden.)

Stimmt das soweit? (Ich hoffe ich habe das mit der boolschen Gleichung nicht zu kompliziert gemacht...)

Nun zu weiteren Abarten von find:

Im 2. Befehl taucht ja jetzt trotzdem immer noch der Eintrag "/etc" auf. (Wieso eigentlich?) Dieser soll jetzt aber auch noch unterdrückt werden. Aus einem Skript (zudem ich evtl. in einem späteren Post noch ein paar Fragen habe) habe ich folgende Lösung:

Code:
me@zombie $ find / -xdev -path /etc -prune -path "/etc/*" -prune -or -user lionel
/mnt/blablub
/usr/src/lionel_test
[...]

Wieso funktioniert dieser Befehl nun, folgende aber nicht:

Code:
me@zombie $ find / -xdev -path "/etc*" -prune -or -user lionel
me@zombie $ find / -xdev \( -path /etc -or -path "/etc/*" \) -prune -or -user lionel

Obwohl auf vielen Seiten erklärt wird, dass man mit den Klammern mehrere Verzeichnisse auf einmal ausschließen kann. (Bei \( -path /etc -or -path /mnt \) funktionierts schließlich auch). Wie gesagt, logisch konsequent ist das wirklich nicht... :-((

Ich hoffe hier kann mir jemand helfen. Bin echt schon seit mehreren Wochen am verzweifeln.

TIA
Crazy-X
 
Hallo
Hoffe mal dir etwas Licht zu bringen.

Zunächst ist es wichtig, sich zu verinnerlichen wie find seine Bedingungen abarbeitet.
Alle Bedingungen werden von Links nach Rechts abgeklappert.
Jeder Ausdruck der wahr ist, führt also zum nächsten Test.
-depht:
Veranlasst find erst den Inhalt zu testen, dann das Verzeichnis selbst.
Wir steigen sozusagen von oben nach unten ab.
Ein ausgeschlossenes Verzeichnis, was davor steht, wird zwar als Verzeichnis ausgeschlossen, aber erst nachdem der Inhalt getestet wurde!
Alles was nun zutrifft gibt find aus bzw wertet weitere Tests aus!
Ein in Klammern zusammengefasster Wert wird als Ganzes betrachtet.
Das bedeutet, wenn der Ausdruck in den Klammern am Ende true liefert, wird nur der Wert true weiter ausgewertet.

Einzelwerte innerhalb der Klammern sind danach transparent.

Nun sollte auch klar werden, warum -prune false liefert, wenn -depht nicht gesetzt ist.
Im Prinzip könntest du -prune mit einem AND ersetzen, mit einer Aussnahme: dass nämlich -depht berücksichtigt wird.

Wenn -prune dann immernoch true liefern würde, würdest du unter Umständen -depth wirkungslos machen.

Wir erinnern uns: -depth testet erst den Inhalt des Verzeichnisses, bevor es das Verzeichnis selbst testet!

Das ist sozusagen eine Möglichkeit die von Links nach Rechts Regel zu umgehen.
Sinnvoll ist das, wenn du z.B. Verzeichnisse mit -exec verschieben willst, weil sonst darin liegende Verzeichnisse nicht mehr gefunden würden.

Hatten wir vor kurzer Zeit erst ein Beitrag hier im Forum.
Hoffe dir etwas beim Verstehen geholfen zu haben.

Gruß Wolfgang
 
Hi,

also erstmal vielen Dank, für deine Hinweise und Tipps! Ich habe zwar eine Weile gebrauch und musste wirklich erstmal verinnerlichen wie find vorgeht. Allerdings habe ich mal noch ein paar Fragen, ob ich das richtig verstanden habe.

Davon ausgehend, dass der Verzeichnisbaum nur folgende Eintäge enthält, würde find also die Eintäger der folgenden Liste hintereinander abarbeiten:

Code:
/etc
/etc/fnord
/etc/fnord2
/etc/testdir
/etc/testdir/shouldnotbefound
/mnt
/mnt/blablub
/usr
/usr/src
/usr/src/lionel_test
/usr/fnord
/usr/lionel_test2
/usr/dir_lionel
/usr/dir_lionel/blablub

Bei einem "find / -xdev -path /etc -prune -or -user lionel" müsste also, wenn ich richtig verstanden habe, folgendes passieren:

find gelangt zum Eintrag "/etc". Deshalb liefert (-path /etc) true, und prune wird ausgewertet. Da prune in diesem Fall true liefert, wird der gesamte Ausdruck (wegen dem Oder) wahr. Und deshalb wird auch /etc ausgegeben!? Dann überspringt find das Verzeichnis und macht mit "/mnt" weiter! Richtig?

Damit aber auch die Ausgabe von "/etc" unterdrückt wird ist in diesem Befehl "find / -xdev -path /etc -prune -path "/etc/*" -prune -or -user lionel" weniger der Test "-path '/etc/*' " schuld, sondern eher der gesamt Ausdruck. Da bei /etc der Test -path "/etc/*" sowieso false ist, wird auch der Gesamtausdruck false (und deshalb auch die Ausgabe von /etc unterdrückt). Vereinfacht stellt der Befehl eigentlich nur das dar: "find / -xdev -path /etc -prune -false -or -user lionel" (wie "dreckig" ^^). Richtig?

Und da bei "find / -xdev \( -path /etc -or -path "/etc/*" \) -prune -or -user lionel", das Verzeichnis "/etc" übersprungen wird, kann der Test -path "/etc/*" eigentlich sowieso nie true werden.

Allerdings habe ich noch keine Idee, wie ich Verzeichnisse auch auschließen kann, wenn ich -depth benötige. Da werde ich aber erstnochmal selbst danach suchen.

TIA
Crazy-X
 

Ähnliche Themen

Zugriff Ubuntu 16.04. auf Freigabe 18.04. LTS nicht möglich

ganze Netzwerkumgebung schagartig unsichtbar - 0S 13.1

Samba 4 Gast Zugang unter Ubuntu funktioniert nicht

Windows clients können nicht mehr auf lange laufendes System zugreifen

dovecot und postfix Konfiguration Problem

Zurück
Oben