Was ist der beste Weg, um "Find" -Ergebnisse zu zählen?
95
Meine derzeitige Lösung wäre find <expr> -exec printf '.' \; | wc -c, aber dies dauert viel zu lange, wenn mehr als 10000 Ergebnisse vorliegen. Gibt es keinen schnelleren / besseren Weg, dies zu tun?
Es ist nicht zuverlässiger, wenn das zu findende Flag -printf auf Ihrer Plattform nicht unterstützt wird. ;-)
Randy Howard
7
Beachten Sie, dass Sie einige weitere Nanosekunden sparen können, indem Sie den Punkt in-printf '.'
Jens
6
@Jens - besonders wenn Sie die Zeit berücksichtigen, die benötigt wird, um das zu tippen
Brian Agnew
6
Bei einem so kleinen Benchmark werden die Timings wahrscheinlich von anderen Faktoren als dem, was Sie messen möchten, dominiert. Ein Experiment mit einem großen Baum wäre nützlicher. Aber das bringt mich dazu, tatsächlich das zu tun, was das OP verlangt hat.
Tripleee
132
Warum nicht
find <expr>| wc -l
als einfache tragbare Lösung? Ihre ursprüngliche Lösung besteht darin ,printf für jede einzelne gefundene Datei einen neuen Prozess zu erstellen, und das ist sehr teuer (wie Sie gerade gefunden haben).
Beachten Sie, dass dies zu viel zählt, wenn Sie Dateinamen mit eingebetteten Zeilenumbrüchen haben, aber wenn Sie diese haben, dann vermute ich, dass Ihre Probleme etwas tiefer gehen.
-1: bricht in der Datei mit Zeilenumbrüchen ab und ist langsamer als das Zählen von Bytes =)
Gilles Quenot
21
Ich glaube nicht, dass dies eine Ablehnung rechtfertigt, da die Beschränkung auf Dateinamen / Zeilenumbrüche ziemlich selten ist und oben erwähnt wurde. Langsamer ? Vielleicht. Angesichts der Tatsache, dass Sie ein Dateisystem abfragen, vermute ich, dass der Geschwindigkeitsunterschied gering ist. Über meine 10.000 Dateien messe ich 3ms Unterschied
Brian Agnew
8
Der Leistungsunterschied zwischen 'find <expr> | wc -l' und 'find <expr> -printf. | wc -c 'sind extrem klein. Das Zwischenspeichern (dh wenn Sie denselben Fund zweimal über denselben Baum ausführen) ist viel wichtiger. IMHO ist die Lösung mit "wc -l" viel intuitiver.
Pitseeker
4
Diese Lösung ist sicherlich langsamer als einige der anderen find -> wcLösungen hier, aber wenn Sie dazu neigten, zusätzlich zu deren Zählung noch etwas anderes mit den Dateinamen zu tun, könnten Sie dies readaus der findAusgabe heraus tun .
n=0while read -r -d '';do((n++))# count# maybe perform another act on filedone<<(find <expr>-print0)
echo $n
Es ist nur eine Modifikation einer in BashGuide gefundenen Lösung, die Dateien mit nicht standardmäßigen Namen ordnungsgemäß verarbeitet, indem das findAusgabetrennzeichen zu einem NUL-Byte gemacht print0und daraus ''(NUL-Byte) als Schleifenbegrenzer gelesen wird.
Dies ist meine countfilesFunktion in meiner ~/.bashrc(es ist ziemlich schnell, sollte für Linux & FreeBSD findfunktionieren und lässt sich nicht von Dateipfaden mit Newline-Zeichen täuschen; das Finale wczählt nur NUL-Bytes):
Antworten:
Versuchen Sie stattdessen (erfordern
find
‚s --printf
Unterstützung):Es ist zuverlässiger und schneller als das Zählen der Zeilen.
Beachten Sie, dass ich die
find
's verwendeprintf
, keinen externen Befehl.Lassen Sie uns ein wenig auf die Bank setzen:
Mein Snippet-Benchmark:
Mit vollen Zeilen:
Meine Lösung ist also schneller =) (der wichtige Teil ist die
real
Linie)quelle
-printf '.'
Warum nicht
als einfache tragbare Lösung? Ihre ursprüngliche Lösung besteht darin ,
printf
für jede einzelne gefundene Datei einen neuen Prozess zu erstellen, und das ist sehr teuer (wie Sie gerade gefunden haben).Beachten Sie, dass dies zu viel zählt, wenn Sie Dateinamen mit eingebetteten Zeilenumbrüchen haben, aber wenn Sie diese haben, dann vermute ich, dass Ihre Probleme etwas tiefer gehen.
quelle
Diese Lösung ist sicherlich langsamer als einige der anderen
find -> wc
Lösungen hier, aber wenn Sie dazu neigten, zusätzlich zu deren Zählung noch etwas anderes mit den Dateinamen zu tun, könnten Sie diesread
aus derfind
Ausgabe heraus tun .Es ist nur eine Modifikation einer in BashGuide gefundenen Lösung, die Dateien mit nicht standardmäßigen Namen ordnungsgemäß verarbeitet, indem das
find
Ausgabetrennzeichen zu einem NUL-Byte gemachtprint0
und daraus''
(NUL-Byte) als Schleifenbegrenzer gelesen wird.quelle
Dies ist meine
countfiles
Funktion in meiner~/.bashrc
(es ist ziemlich schnell, sollte für Linux & FreeBSDfind
funktionieren und lässt sich nicht von Dateipfaden mit Newline-Zeichen täuschen; das Finalewc
zählt nur NUL-Bytes):quelle