Wie kann ich die Anzahl der Dateien in einem Verzeichnis über die Befehlszeile ermitteln?


193

Ich habe ein Verzeichnis mit einer großen Anzahl von Dateien. Ich sehe keinen lsSchalter, um die Zählung bereitzustellen. Gibt es etwas Befehlszeilenmagie, um die Anzahl der Dateien zu ermitteln?



tree . | tailoder tree -a . | tailversteckte Dateien / Verzeichnisse einzuschließen, treeist rekursiv, wenn Sie dies wünschen.
CodyChan

Antworten:


239

Verwendung einer breiten Definition von "Datei"

ls | wc -l

(Beachten Sie, dass versteckte Dateien nicht gezählt werden und dass Dateinamen keine Zeilenumbrüche enthalten).

Der kanonische Weg, um versteckte Dateien (außer .und ..) einzuschließen und Probleme mit Zeilenumbrüchen zu vermeiden, ist:

find . ! -name . -prune -print | grep -c /

Oder rekursiv:

find .//. ! -name . -print | grep -c //

23
wcist ein "Word Count" -Programm. Der -lSchalter veranlasst es, Zeilen zu zählen. In diesem Fall werden die Zeilen in der Ausgabe von gezählt ls. Auf diese Weise wurde mir auch immer beigebracht, die Anzahl der Dateien für ein bestimmtes Verzeichnis zu ermitteln.
Sandy

20
Bitte beachten Sie, dass lsdies ls -1der Fall ist, wenn der Ausgang eine Pipe ist.
Lesmana

6
Das bringt nicht alles in ein Verzeichnis - Sie haben Punktedateien verpasst und auch ein paar zusätzliche Zeilen gesammelt. Ein leeres Verzeichnis gibt weiterhin 1 Zeile zurück. Und wenn Sie anrufen ls -la, erhalten Sie drei Zeilen im Verzeichnis. Sie möchten ls -lA | wc -ldie Einträge .und überspringen ... Sie werden jedoch immer noch einsam sein.

1
Ein leeres Verzeichnis gibt 0 für mich zurück
James Roth

2
Ein korrigierter Ansatz, bei dem Dateien mit Zeilenumbrüchen im Namen nicht doppelt gezählt werden, wäre folgender: ls -q | wc -l- Beachten Sie jedoch, dass versteckte Dateien bei diesem Ansatz immer noch nicht gezählt werden und Verzeichnisse gezählt werden.
Godlygeek

31

Für eine enge Definition der Datei:

 find . -maxdepth 1 -type f | wc -l

Und Sie können natürlich das -maxdepth 1zum rekursiven Zählen von Dateien weglassen (oder es für die gewünschte maximale Suchtiefe einstellen).
User7089

1
Wenn Sie eine Datei haben, deren Name eine neue Zeile enthält, wird diese bei diesem Ansatz fälschlicherweise zweimal gezählt.
Godlygeek

7
Ein korrigierter Ansatz, bei dem Dateien mit Zeilenumbrüchen im Namen nicht doppelt gezählt werden, wäre:find -maxdepth 1 -type f -printf "\n" | wc -l
godlygeek

+1 Erlaube versteckte Dateien und ignoriere Verzeichnisse
Michael Durrant

14
ls -1 | wc -l

...

$ ls --help | grep -- '  -1'
    -1                         list one file per line

...

$ wc --help | grep -- '  -l'
    -l, --lines            print the newline counts

PS: Beachten Sie ls - <Nummer Eins> | wc - <Buchstabe-l>


10
Die meisten Versionen von lsnicht -1automatisch , wenn die Ausgabe an ein Rohr ist.
Dennis Williamson

3
@Dennis Das ist interessant Ich wusste nicht, dass eine Anwendung erkennen kann, dass die Ausgabe an eine Pipe geht.
Xenoterracide

1
Ich habe diese Version überarbeitet, da sie expliziter ist. Obwohl ja, ls verwendet -1, wenn es weitergeleitet wird (probieren Sie es aus: ls | cat), finde ich die -1-Syntax expliziter.
gabe.

3
@xenoterracide: In Bash:[[ -p /dev/stdin ]] && echo "stdin is from a pipe"
Dennis Williamson

2
In meinen Tests war es deutlich schneller, auch die Option -f anzugeben, um ein Sortieren der Dateinamen zu vermeiden. Leider erhalten Sie immer noch die falsche Antwort, wenn Ihre Dateinamen Zeilenumbrüche enthalten.
Samuel Edwin Ward

10

Die wahrscheinlich vollständigste Antwort mit ls/ wcpair ist

ls -Aq | wc -l

Wenn Sie Punktedateien zählen möchten, und

ls -q | wc -l

Andernfalls.

  • -APunktedateien zu zählen, aber wegzulassen .und ...
  • -qmachen lsersetzen nongraphic Zeichen, insbesondere Zeilenende- Marke, mit ?, Ausgabe 1 Zeile für jede Datei machen

Um eine einzeilige Ausgabe über das lsIn-Terminal zu erhalten (dh ohne sie weiterzuleiten wc), muss die -1Option hinzugefügt werden.

(Verhalten lsgetestet mit Coreutils 8.23)


2
Wie du gesagt hast, -1wird nicht benötigt. In Bezug auf „es Zeilenumbrüche in Dateinamen vernünftig mit Konsolenausgabe behandelt“ , ist dies , weil der -qSchalter (die Sie statt verwenden sollten , -bweil es tragbar) , die „Kräfte jede Instanz nicht druckbaren Dateinamen Zeichen und <Tab> Zeichen geschrieben werden Implementierungen können diese Option standardmäßig bereitstellen, wenn die Ausgabe an ein Endgerät erfolgt. " Also zB ls -Aq | wc -lum alle Dateien / Verzeichnisse ls -qp | grep -c /zu zählen oder nur nicht versteckte Verzeichnisse usw. zu zählen ...
don_crissti

Danke für deinen Beitrag. Geändert -bzu -q.
Frax

7

Wenn Sie wissen, dass das aktuelle Verzeichnis mindestens eine nicht ausgeblendete Datei enthält:

set -- *; echo "$#"

Dies ist offensichtlich für jeden Glob verallgemeinerbar.

In einem Skript hat dies den manchmal unglücklichen Nebeneffekt, dass die Positionsparameter überschrieben werden. Sie können das umgehen, indem Sie eine Subshell oder eine Funktion (Bourne / POSIX-Version) wie folgt verwenden:

count_words () {
  eval 'shift; '"$1"'=$#'
}
count_words number_of_files *
echo "There are $number_of_files non-dot files in the current directory"

Eine alternative Lösung ist $(ls -d -- * | wc -l). Wenn das Glob ist *, kann der Befehl auf gekürzt werden $(ls | wc -l). Das Parsen der Ausgabe von lsmacht mir immer unangenehm, aber hier sollte es funktionieren, solange Ihre Dateinamen keine Zeilenumbrüche enthalten oder Sie lssie maskieren . Und $(ls -d -- * 2>/dev/null | wc -l)hat den Vorteil, dass der Fall eines nicht übereinstimmenden Glob ordnungsgemäß behandelt werden kann (dh, in diesem Fall wird 0 zurückgegeben, wohingegen bei der set *Methode sorgfältig geprüft werden muss, ob der Glob möglicherweise leer ist).

Wenn Dateinamen Zeilenumbrüche enthalten können, können Sie auch eine Alternative verwenden $(ls -d ./* | grep -c /).

Jede dieser Lösungen, die darauf angewiesen sind, die Erweiterung eines Glob zu übergeben, schlägt lsmöglicherweise mit einer zu langen Argumentliste fehl, wenn viele übereinstimmende Dateien vorhanden sind.


1
Möchten Sie wirklich 13.923 Positionsparameter erstellen? Und Sie sollten Ihre lokale Variable erstellen localoder entfernen: eval $1=$#oder einfach verwenden echo $#und tun number_of_files=$(count_words *).
Dennis Williamson

1
@ Tennis: Ein Teil des Punktes war, das Gabeln zu vermeiden. Ich denke, das ist kein Problem des 21. Jahrhunderts. Ok, ich gebe zu, ich interessiere mich nicht mehr für Nicht-POSIX-Shells, also hätte ich die temporäre Variable vermeiden können.
Gilles

Warum haben Sie einen davon abgezogen $#(das hatten Sie vor der Bearbeitung noch nicht getan)?
Dennis Williamson

@Dennis: Ich vermeide immer noch einen Fork (naja, das macht einen Unterschied auf Computern mit einer langsamen CPU wie Routern) und übergebe einen Variablennamen als $1. Was ich zählen möchte, ist die Anzahl der Parameter, die nicht der erste Parameter sind. (Ich kann nicht verwenden, shiftweil ich den Variablennamen behalten muss.) (Ähm, wenn Sie jetzt nach der ersten Zeile gefragt hätten ...)
Gilles

@Dennis: denk mal drüber nach, ich kann es gebrauchen shiftwenn ich es mal richtig mache .
Gilles

7

Ich habe du --inodesnützlich gefunden , bin mir aber nicht sicher, welche Version dues erfordert. Es sollte wesentlich schneller sein als alternative Ansätze mit findund wc.

Unter Ubuntu 17.10 funktioniert Folgendes:

du --inodes      # all files and subdirectories
du --inodes -s   # summary
du --inodes -d 2 # depth 2 at most

Kombiniere mit | sort -nr, um absteigend nach der Anzahl der enthaltenen Inodes zu sortieren.


5

Wenn wir mit ls / wc pair -U hinzufügen, ist dies viel schneller (nicht sortieren).

ls -AqU | wc -l

1
-Uist allerdings GNU-spezifisch.
Stéphane Chazelas

4

Geben Sie nach der Installation des Befehls tree Folgendes ein:

tree

Wenn du auch versteckte Dateien haben willst:

tree -a

Wenn Sie Debian / Mint / Ubuntu Linux verwenden, geben Sie den folgenden Befehl ein, um den Baumbefehl zu installieren:

sudo apt-get install tree

Mit der Option -L wird die maximale Anzeigeebene des Verzeichnisbaums festgelegt. Der Befehl tree zählt nicht nur die Anzahl der Dateien, sondern auch die Anzahl der Verzeichnisse. Dabei werden so viele Ebenen des Verzeichnisbaums berücksichtigt, wie Sie möchten.


Wenn ich tree eingebe, wird eine Art Baum auf dem Bildschirm des Verzeichnisses ausgegeben, in dem ich mich befinde, aber ich kann nicht sehen, wo die Anzahl der Dateien angezeigt wird.
Charles Darwin

2
find -maxdepth 1 -type f -printf . | wc -c
  • -maxdepth 1macht es nicht rekursiv, findist standardmäßig rekursiv
  • -type f schließt nur Dateien ein
  • -printf .ist eine süße Geste. Es wird ein Punkt für jede Datei anstelle des Dateinamens gedruckt. Jetzt kann jeder Dateiname verarbeitet und Daten gespeichert werden. wir müssen nur die Punkte zählen :)
  • | wc -c zählt Zeichen

1

Keine Pfeife, keine Schnurkopie, keine Gabel, nur einen Liner

$ fcount() { local f i=0; for f in *; do let i++; done; echo $i; }; fcount

1
Gibt den Wert 1 zurück, wenn sich keine Dateien im Verzeichnis befinden. Zählt keine Dateien, zählt Dateien und Verzeichnisse.
Steve

1

Hier ist eine andere Technik in Anlehnung an Gilles :

word_count () { local c=("$@"); echo "${#c[@]}"; }
file_count=$(word_count *)

Dadurch wird ein Array mit 13.923 Elementen erstellt (wenn es so viele Dateien gibt).


Was ist der Sinn dieses cArrays? word_count() { echo "$#"; }wäre genug. Die Lösung von @Gilles besteht darin, den Zählerstand in einer zurückgegebenen Variablen zu speichern, um zu vermeiden, dass eine Befehlssubstitution verwendet werden muss (bei der ein Fork und eine Pipe in anderen Shells als ksh93 verwendet werden).
Stéphane Chazelas

1
find . -type f -maxdepth 1 |  wc -l 

Dies kann nur die Dateien im aktuellen Verzeichnis auflisten.


find . -type ffindet Dateien im aktuellen Verzeichnis und rekursiv auch in Unterverzeichnissen.
Dhag

0

Versuchen Sie dies, ich hoffe, diese Antwort wird Ihnen helfen

echo $((`ls -l | wc -l` -1 ))


0

Einige der zuvor gegebenen Antworten wurden verbessert, diesmal jedoch explizit.

$ tree -L 1 | tail -n 1 | cut -d " " -f 3

Es ist wert, die Verwendung einiger geliebter Befehle wie tailund zu bemerken cut. Beachten Sie außerdem, dass die Struktur standardmäßig nicht verfügbar ist. Der obige Befehl erfasst zuerst Informationen über das Verzeichnis auf Ebene 1, erhält dann die letzte Zeile, tail -n 1in der sich unser Ziel befindet, und endet damit cut, das dritte Wort zu nehmen.

Zum Beispiel suchen in /:

/ $ tree -L 1
.
├── 1
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
├── lib -> usr/lib
├── lib64 -> usr/lib64
├── lost+found
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
└── var

20 directories, 1 file
/ $ tree -L 1 | tail -n 1
20 directories, 1 file
/ $ tree -L 1 | tail -n 1 | cut -d " " -f 3
1

Wie wäre es dann mit der Frage nach der Anzahl der Verzeichnisse?



Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.