Was teuer ist, sind Systemaufrufe für die Dateien (für die Systemaufrufe selbst und für die E / A).
Solche Dinge -type
, -mtime
erfordern einen lstat(2)
auf dem Dateisystemaufruf. -name
, -path
, -regex
Nicht (obwohl natürlich wird es getan Systemaufrufe auf die Verzeichnisse haben sie enthalten , ihre Inhalte zu lesen).
In der find
Regel wird eine lstat()
ohnehin (weil es wissen muss, ob eine Datei ein Verzeichnis ist oder nicht, um in sie abzusteigen, es sei denn, diese Informationen sind im enthalten readdir()
), aber es gibt Fälle, in denen es ohne sie auskommen kann. Wenn beispielsweise die Anzahl der Links eines Verzeichnisses weniger als 3 beträgt, find
weiß es in einigen Dateisystemen, dass es keine Unterverzeichnisse hat, und einige find
Implementierungen werden optimiert, indem dort kein lstat
s ausgeführt wird.
-xtype
wird ein verursachen stat(2)
, -printf ...
, -ls
verursachen ein stat()
, lstat()
, readlink()
, -lname
a lstat()
und readlink()
.
Deshalb möchten Sie vielleicht das -name
/ -path
/ -regex
... an die erste Stelle setzen. Wenn sie eine Datei ausschließen können, können sie einen oder mehrere Systemaufrufe vermeiden.
Nun, ein ist -regex
vielleicht teurer als ein -name
, aber ich bin mir nicht sicher, ob Sie durch den Austausch viel erreichen würden.
Beachten Sie auch, dass einige find
Implementierungen wie GNU find
die Prüfungen nach Möglichkeit standardmäßig neu anordnen. Sehen:
info find 'Optimisation Options'
auf einem GNU-System ( dort auf gnu.org für die neueste Version von GNU findutils
).
Wenn Sie Ihre Tests auf einem GNU-System durchgeführt hätten, würden beide Befehle normalerweise dasselbe tun, da find
sie den -name
Vorgang ohnehin vorwärts verschoben hätten .
Damit das -type d -name ...
vs -name ... -type d
einen Unterschied macht, benötigen Sie eine find
Implementierung, die nicht durch Neuanordnen dieser Prädikate optimiert wird, und eine Implementierung, die einige Optimierungen vornimmt, indem nicht lstat()
für jede Datei eine durchgeführt wird.
Wo es unabhängig von der Implementierung einen (großen) Unterschied geben wird, ist:
find . -name 'x*' -exec test -d {} \; -print
vs:
find . -exec test -d {} \; -name 'x*' -print
find
Ich kann das nicht neu anordnen, -exec
da dies zu Funktionsunterschieden führen kann ( find
ich kann nicht wissen, ob der ausgeführte Befehl nur zum Testen dient oder etwas anderes tut).
Und natürlich -exec ... {} \;
ist es mehrere Größenordnungen teurer als jedes andere Prädikat, da es bedeutet, einen Prozess zu verzweigen und einen Befehl darin auszuführen (der selbst viele Systemaufrufe ausführt) und auf ihn und seinen Exit-Code zu warten.
$ time find /usr/lib -exec test -d {} \; -name z\* -print > /dev/null
1.03s user 12.52s system 21% cpu 1:03.43 total
$ time find /usr/lib -name z\* -exec test -d {} \; -print > /dev/null
0.09s user 0.14s system 62% cpu 0.367 total
(Die erste ruft test
jede Datei in /usr/lib
(56685) auf, die zweite nur für die Dateien, deren Name mit z
(147) beginnt .)
Beachten Sie, dass dies -exec test -d {} \;
nicht dasselbe ist wie -type d
. Es ist das tragbare Äquivalent der GNU-spezifischen -xtype d
.
-name ..
und von-type d
Bedeutung ist. Ihre Tests scheinen darauf hinzudeuten, dass dies nicht der Fall ist.