Wie zähle ich alle Dateien rekursiv durch Verzeichnisse

47

Ich möchte sehen, wie viele Dateien sich in Unterverzeichnissen befinden, um herauszufinden, wo sich die gesamte Inode-Nutzung auf dem System befindet. Ein bisschen wie ich würde dies für die Raumnutzung tun

du -sh /*

Das gibt mir den Platz, der in den Verzeichnissen außerhalb von root verwendet wird, aber in diesem Fall möchte ich die Anzahl der Dateien, nicht die Größe.

Xenoterracid
quelle
Siehe auch Alle Dateien in einem Verzeichnis rekursiv zählen , Dateien in jedem Verzeichnis zählen? bei SU.
Gilles 'SO- hör auf böse zu sein'
Ich denke, dass "wie viele Dateien in Unterverzeichnissen in dort Unterverzeichnissen sind" eine verwirrende Konstruktion ist. Wenn Sie genauer angeben, was Sie möchten, erhalten Sie möglicherweise eine Antwort, die der Rechnung entspricht.
Steven D
@Steven zögern Sie nicht, es umzuschreiben ... Ich dachte, mein Beispiel du -sh /*machte ziemlich deutlich, wie ich wollte, dass der Zähler funktioniert. Zähle einfach die Dateien und nicht die Bytes.
Xenoterracide
Wie Sie Inode-Verwendung erwähnen, verstehe ich nicht, ob Sie die Anzahl der Dateien oder die Anzahl der verwendeten Inodes zählen möchten. Die beiden unterscheiden sich, wenn im Dateisystem feste Verknüpfungen vorhanden sind. Die meisten, wenn nicht alle Antworten geben die Anzahl der Dateien an. Verwenden Sie sie nicht auf einer Apple Time Machine-Sicherungsdiskette.
mouviciel
@mouviciel dies wird nicht auf einer Sicherungsdiskette verwendet, und ja, ich nehme an, dass sie unterschiedlich sind, aber in der Umgebung, in der ich mich befinde, gibt es nur sehr wenige Hardlinks. Technisch muss ich nur ein Gefühl dafür bekommen. Finde heraus, wo da draußen jemand brennt.
Xenoterracide

Antworten:

60
find -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done

Vielen Dank an Gilles und Xenoterracide für die Sicherheits- und Kompatibilitätsverbesserungen.

Der erste Teil: find -maxdepth 1 -type dGibt eine Liste aller Verzeichnisse im aktuellen Arbeitsverzeichnis zurück. Dies wird geleitet, um ...

Der zweite Teil: while read -r dir; dobeginnt eine while-Schleife - solange die in die while kommende Pipe offen ist (bis die gesamte Verzeichnisliste gesendet wurde), setzt der Lesebefehl die nächste Zeile in die Variable "dir". Dann geht es weiter ...

Der dritte Teil: printf "%s:\t" "$dir";gibt die Zeichenfolge in "$ dir" (der einen der Verzeichnisnamen enthält) gefolgt von einem Tabulator aus.

Der vierte Teil: find "$dir -f file"Erstellt eine Liste aller Dateien innerhalb des Verzeichnisnamens in "$ dir". Diese Liste wird gesendet an ..

Der fünfte Teil: wc -l;Zählt die Anzahl der Zeilen, die in die Standardeingabe gesendet werden.

Der letzte Teil: doneBeendet einfach die while-Schleife.

So erhalten wir eine Liste aller Verzeichnisse im aktuellen Verzeichnis. Für jedes dieser Verzeichnisse erstellen wir eine Liste aller darin enthaltenen Dateien, damit wir sie alle mit zählen können wc -l. Das Ergebnis sieht folgendermaßen aus:

./dir1: 234
./dir2: 11
./dir3: 2199
...
Shawn J. Goff
quelle
Verwenden Sie Backslashes immer read -rals readSpezialbehandlung. Dann echo -en "$dir:\t"werden wieder Backslashes entstellt; Eine einfache Lösung ist, printf '%s:\t' "$dir"stattdessen zu verwenden . Als nächstes $dirsollte "$dir"(verwenden Sie immer doppelte Anführungszeichen um variable Substitutionen ).
Gilles 'SO - hör auf böse zu sein'
Geändert nach find -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" | wc -l; done
@
2
Ich sort -n -r -k2
füge
Der vierte Teil: find "$ dir" erstellt eine Liste aller Dateien innerhalb des Verzeichnisnamens in "$ dir". Sie haben vergessen, hinzuzufügen -type f, um es Dateien find -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done
aufzulisten
@ krzysiek-boduch Danke! Ich habe die Antwort aktualisiert.
Shawn J. Goff
15

Versuchen Sie find . -type f | wc -l, es werden alle Dateien im aktuellen Verzeichnis sowie alle Dateien in Unterverzeichnissen gezählt. Beachten Sie, dass nicht alle Verzeichnisse als Dateien gezählt werden, sondern nur normale Dateien.

herohuyongtao
quelle
13

Hier ist eine Zusammenstellung einiger nützlicher Auflistungsbefehle (basierend auf dem Code früherer Benutzer neu gehasht):

Liste der Ordner mit der Anzahl der Dateien:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type f | wc -l); printf "%4d : %s\n" $n "$dir"; done

Listen Sie Ordner mit einer ungleichen Anzahl von Dateien auf:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type f | wc -l); if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Ordner mit Unterordneranzahl auflisten:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type d | wc -l); let n--; printf "%4d : %s\n" $n "$dir"; done

Listen Sie Ordner mit einer Unterordneranzahl ungleich Null auf:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type d | wc -l); let n--; if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Leere Ordner auflisten:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" | wc -l); let n--; if [ $n -eq 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Liste nicht leerer Ordner mit Inhaltsanzahl:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" | wc -l); let n--; if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done
DolphinDream
quelle
Und übrigens, wenn Sie die Ausgabe eines dieser Listenbefehle nach der Anzahl der Elemente sortieren möchten. Leiten Sie den Befehl in eine Sortierung um: "a-list-command" | sort -n
DolphinDream
12

Versuchen:

find /path/to/start/at -type f -print | wc -l

als Ausgangspunkt oder wenn Sie wirklich nur die Unterverzeichnisse eines Verzeichnisses durchsuchen möchten (und die Dateien in diesem Verzeichnis der obersten Ebene überspringen möchten)

find `find /path/to/start/at -mindepth 1 -maxdepth 1 -type d -print` -type f -print | wc -l
Schrei Havok
quelle
+1 für etwas | wc -l ... Wortzahl ist so ein schönes kleines Werkzeug
Johan
Ja, aber dies macht nur 1 Verzeichnis ... Ich möchte die Anzahl aller Verzeichnisse in einem Verzeichnis ermitteln und möchte sie nicht jedes Mal einzeln ausführen ... Natürlich könnte ich eine Schleife verwenden ... aber ich bin faul.
Xenoterracide
findArbeitet standardmäßig rekursiv durch alle Unterverzeichnisse. Wenn Sie möchten, dass es an mehreren Orten funktioniert, können Sie alle zwischen findund angeben -type.
Didier Trosset
das zweite funktioniert sicher nicht .... ich habe es zuhause ausprobiert. Ich habe bekommen 698035 . Ich sollte ungefähr 6 Zahlen sehen.
Xenoterracide
Es funktioniert für mich - sind Sie sicher, dass Sie nur 6 Dateien unter haben /home? Ich wäre mir zu 100% sicher, dass Sie das nicht tun.
Cry Havok
4

Die folgende Lösung zählt die tatsächliche Anzahl der verwendeten Inodes ab dem aktuellen Verzeichnis:

find . -print0 | xargs -0 -n 1 ls -id | cut -d' ' -f1 | sort -u | wc -l

Um die Anzahl der Dateien derselben Teilmenge zu ermitteln, verwenden Sie:

find . | wc -l

Bei Lösungen, die nur Unterverzeichnisse durchsuchen, ohne die Dateien im aktuellen Verzeichnis zu berücksichtigen, können Sie auf andere Antworten verweisen.

mouviciel
quelle
1
Gute Idee, harte Links zu berücksichtigen. Unter der Annahme , GNU find, brauchen Sie nicht so viele Schritte: find -printf '%i\n' | sort -u | wc -l. Wenn Sie portabel sein möchten, müssen Sie find . -exec ls -id {} + | cut …stattdessen.
Gilles 'SO - hör auf böse zu sein'
2

OS X 10.6 unterbricht den Befehl in der akzeptierten Antwort, da kein Pfad für angegeben wird find. Verwenden Sie stattdessen:

find . -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done
abeboparebop
quelle
2

Ich weiß, dass ich zu spät zur Party komme, aber ich glaube, dass diese reine bash(oder andere Shell, die Double Star Glob akzeptiert) Lösung in einigen Situationen viel schneller sein könnte:

shopt -s globstar    # to enable ** glob in bash
for dir in */; do a=( "$dir"/**/* ); printf "%s\t%s\n" "$dir:" "${#a[*]}"; done

Ausgabe:

d1/:    302
d2/:    24
d3/:    640
...
jimmij
quelle
1

Probieren Sie es aus:

find -type d -print0 | xargs -0 -I {} sh -c 'printf "%s\t%s\n" "$(find "{}" -maxdepth 1 -type f | wc -l)" "{}"'

Es sollte gut funktionieren, es sei denn, Dateinamen enthalten Zeilenumbrüche.

Dennis Williamson
quelle
viel zu rekursiv ... Ich möchte nur die oberste Ebene sehen, in der sich alles darunter befindet. summiert ... dies führt dazu, dass jedes Verzeichnis gedruckt wird.
Xenoterracide
@xenoterracide: Versuchen Sie, -maxdepth 1sofort nach dem ersten hinzuzufügen find. Wenn Sie die Anzahl der Unterverzeichnisse in Ihre Zählung einbeziehen möchten, entfernen Sie das -type fam Ende (das hätte eigentlich ! -type dsowieso so sein müssen, dass alle Nicht-Verzeichnisdateien eingeschlossen worden wären).
Dennis Williamson
1

Wenn Sie die ncduinstalliert haben (ein Muss, wenn Sie eine Bereinigung durchführen möchten), geben Sie einfach c"Anzeige der Anzahl der untergeordneten Elemente umschalten" ein. Und Czu "Nach Artikeln sortieren".

Demi-Lune
quelle
1
lol, das muss die am häufigsten akzeptierte Antwort sein :)
x-yuri
0

du - inodes

Ich bin mir nicht sicher, warum niemand (ich selbst eingeschlossen) wusste:

du --inodes
--inodes
      list inode usage information instead of block usage

Ich bin mir ziemlich sicher, dass dies das Problem des OP löst. Ich habe viel damit angefangen, um herauszufinden, wo sich all der Müll in meinen riesigen Laufwerken befindet (und um ihn auf eine ältere Festplatte auszulagern).

Weitere Infos

Wenn Sie NICHT wiederkehren möchten (was in anderen Situationen nützlich sein kann), fügen Sie hinzu

-S, --separate-dirs
Sridhar Sarnobat
quelle