Ihr Ansatz kurz nicht nur gefallen, weil die Shell Ihre Befehlsersetzungen erweitert ($(...)
) vorne, aber im Grunde, weil können Sie nicht Shell Befehlszeilen übergeben direkt bis find
:
find
‚s -exec
Aktion kann nur aufrufen externe Dienstprogramme mit literal Argumente - die einzige nicht literal unterstützt Argument ist die {}
die den Dateinamen (n) an die Hand.
choroba's answer behebt sofortige Ihr Problem durch eine separate Shell-Instanz bei jeder Iteration, der als Argument übergeben Zeichenfolge auszuführen, um die Shell-Befehl zum Aufrufen wird (-exec bash -c '...' \;
).
Das funktioniert zwar (vorausgesetzt, Sie den {}
Wert als Argument übergeben anstatt es in der Befehlszeilen-Zeichenfolge Einbettung), es ist auch ganz ineffizient, weil mehrere untergeordnete Prozessefür jeden Eingang erstellt werden Datei.
(Während es ein Weg ist find
Pass (in der Regel), um alle Eingabedateien zu einem (in der Regel) einzigen Aufruf des angegebenen externen Dienstprogramm zu haben - nämlich mit Terminator +
statt \;
, dann ist dies nicht eine Option, hier aufgrund der Art der Befehlszeile übergeben.)
ein effiziente und robuste [1] Implementierung, die die Anzahl der Kind minimiert erstellt verarbeitet wie folgt aussehen würde:
Anmerkung: Ich gehe davon aus GNU Dienstprogramme hier durch Verwendung von head -n -1
und sort -h
.
Auch ich bin Begrenzung find
‚s Ausgabe Dateien nur (wie bei den Verzeichnissen im Gegensatz), weil wc -l
funktioniert nur auf Dateien.
paste <(find . -type f -exec du -h {} +) <(find . -type f -exec wc -l {} + | head -n -1) |
awk -F'\t *' 'BEGIN{OFS="\t"} {sub(" .+$", "", $3); print $1,$2,$3}' |
sort -h -t$'\t' -k1,1
Beachten Sie die Verwendung von -exec ... +
statt -exec ... \;
, die das an einem einzigen Aufruf an das externe Programm übergeben typischerweise alle Eingabedateinamen zu sichern hat (wenn nicht alle Dateinamen passen auf eine einzige In der Befehlszeile werden Aufrufe effizient gebündelt, um möglichst wenige Anrufe zu tätigen.
wc -l {} +
gibt immer eine Zusammenfassungszeile aus, die head -n -1
entfernt, aber auch Dateinamen nach jeder Zeilenanzahl ausgibt.
paste
kombiniert die Zeilen jedes Befehls (deren jeweilige Eingaben von einer Prozesssubstitution stammen. <(...)
) in einen einzelnen Ausgabestrom.
Der Befehl awk
entfernt dann den überflüssigen Dateinamen, der von wc
stammt, am Ende jeder Zeile.
Schließlich wird der Befehl sort
sortiert das Ergebnis durch die 1. (-k1,1
) laschen getrennt (-t$'\t'
) Säule durch Menschen lesbaren Zahlen (-h
), wie die Zahlen, die du -h
Ausgänge (z.B. 1K
).
[1] Wie bei jeder Linie -orientierten Verarbeitung, Dateinamen mit eingebettetem newlines nicht unterstützt werden, aber ich halte dies nicht für eine reale Problem.
Zeigen Sie uns, was Sie bekommen haben – eckes
@eckes bearbeitet mit nicht funktionierendem Code – Hatshepsut