Zählen Sie die Gesamtzahl der Dateien in einem bestimmten Verzeichnis mit einer bestimmten Erweiterung

32

Ich möchte die Gesamtzahl der Dateien in einem bestimmten Verzeichnis zählen, die mit der Erweiterung ".mp4" enden.

Ich erhalte folgenden Befehl:

ls -F |grep -v / | wc -l

Es zählt alle Dateien in einem bestimmten Verzeichnis, aber ich möchte die Anzahl der Dateien, die mit der Erweiterung .mp4 enden.

Gibt es einen Ubuntu-Befehl dafür?

Prakash V Holkar
quelle
2
Die einfache, korrekte und unkomplizierte Antwort lautet @ louis-matthijssen one. ls -1Die Behandlung von Zeilenumbrüchen macht es in diesem Fall sinnvoll, die lsAusgabe zu analysieren . Das markierte ist für die Verwendung des Flags -R falsch.
Rmano

Antworten:

19

Hier kann man das so machen

ls -lR /path/to/dir/*.jpg | wc -l

Das gibt dir Zählung

sk1712
quelle
5
Warum das -R? Warum eine vollständige Datei erstellen, statwenn Sie nur den Dateinamen benötigen? Warum nicht ls -1 *.jpg| wc -l? (ok, funktioniert nicht, wenn Sie Dateinamen mit Zeilenumbrüchen haben. In diesem Fall haben Sie es verdient ;-) ...)
Rmano
2
... und die Frage lautete "Zählen der Anzahl der Dateien in einem Verzeichnis". Darüber hinaus werden alle Inhalte von Unterverzeichnissen, deren Name mit .jpg endet, rekursiv aufgelistet , nicht Dateien in Unterverzeichnissen, die mit .jpg enden .jpg. Hast du es jemals getestet?
Rmano
1
Die Frage lautet "Dateien in einem bestimmten Verzeichnis", was impliziert, dass eine Rekursion von Unterverzeichnissen nicht erwünscht ist.
David Richerby
1
Dies schlägt auch fehl, wenn sich zu viele Dateien im Verzeichnis befinden (da diese *.jpgdurch die Shell und nicht durch erweitert werden ls) und wenn Dateien vorhanden sind, deren Namen mit Bindestrichen beginnen.
David Richerby
2
@DavidRicherby Hiermit werden Namen übersprungen, die mit beginnen .. Bei Bindestrichen in Namen funktioniert dies jedoch in Ordnung, es sei denn, es /path/to/dirhandelt sich um eine leere Zeichenfolge oder einen relativen Pfad, der mit einem Bindestrich beginnt. Aber ich habe mich vorher geirrt , gesagt, lsZeichen werden durch ersetzt ?. Das passiert, wenn stdout ein Terminal ist, aber hier ist die Ausgabe eine Pipe, also werden lsalle Zeichen von Dateinamen an gesendet wc. Das macht diese Antwort falsch, ohne das -qoder-b -Flag , um dieses Verhalten zu ändern , da Dateinamen Zeilenumbrüche enthalten können. Die Antwort von l0b0 ist frei von diesen Problemen.
Eliah Kagan
42

Leider ist dieses harmlose Problem auf eine Weise schwer zu lösen, die alle Dateinamen unterstützt und portierbar ist. Dies ist sicher (es behandelt versteckte Dateien, Pfade mit Leerzeichen, Bindestrichen und sogar Zeilenumbrüchen) und POSIX-kompatibel :

find /path/to/directory -mindepth 1 -type f -name "*.mp4" -printf x | wc -c

Wenn Sie nicht möchten, dass es rekursiv ist, fügen Sie einfach hinzu -maxdepth 1.

Sie sollten die lsAusgabe nicht analysieren .

Prüfung:

$ cd -- "$(mktemp -d)"
$ touch -- -foo.mp4 .bar.mp4 .bat.mp4 'baz.mp4
> ban.mp4'
$ find . -mindepth 1 -type f -name "*.mp4" -exec printf x \; | wc -c
4

Vergleichen mit der akzeptierten Antwort :

$ ls -lR ./*.mp4 | wc -l
3

Oder andere Vorschläge:

$ find . -name "*.mp4" | wc -l
5
$ ls -1 *.mp4 | wc -l
ls: invalid option -- '.'
Try 'ls --help' for more information.
0
$ find . -name "*.mp4" | wc -c # Answer fixed at a later time
51
$ find . -name "*.mp4" | wc -l
5
$ find . | grep -i ".mp4$" | wc -l
5
$ ls . | grep ".mp4$" | wc -l
3
l0b0
quelle
2
Obwohl diese Antwort korrekt und robust ist, können Sie sie -printf xanstelle von verwenden -exec printf x \;. Das heißt: find /path/to/directory -mindepth 1 -type f -name "*.mp4" -printf x | wc -c Es gibt keine Notwendigkeit an -execden externen printfBefehl, der , wenn es viele Dateien werden sehr langsam , da findmuss Gabel (2) aus einer Kopie von sich selbst und dann execve (2) /usr/bin/printf . Mit -exec printf x \;muss das für jede Datei einmal gemacht werden .
Eliah Kagan
-printfwird in POSIX nicht unterstütztfind , weshalb ich es nicht verwendet habe.
l0b0
1
Weder sind -mindepthund -maxdepth, was du benutzt hast.
Eliah Kagan
Guter Punkt, ich hatte das nicht verstanden!
10.
BSD findenthält -mindepthund enthält -maxdepthaber nicht, -printfso schätze ich die Aufnahme von beiden.
Joseph
11

Dieser findet, sortiert und listet alle Dateien nach Erweiterung in der folgenden Reihenfolge auf:

find . -type f | sed 's/.*\.//' | sort | uniq -c
squozen
quelle
Ausgezeichnet! Ich würde einfach ein | sort -rnam Ende und vielleicht ein -mindepth 1wenn nur aktuelles Verzeichnis hinzufügen .
Pablo A
Und vielleicht Pipe head -n, um die Spitze n zu bekommen.
Raman
so eine tolle Antwort, vielen Dank
Dennis Golomazov
5

Ich denke, es ist sehr einfach, Befehle zu befolgen.

$ find . -name "*.mp4" | wc -l
8

oder

$ find . | grep -i ".mp4$" | wc -l
8

Ich denke, dass die obigen Befehle die Anzahl der Dateien und Verzeichnisnamen berechnen *.mp4

Daher schlage ich vor, dass Sie die folgende -type fOption als findParameter verwenden.

$ find . -name "*.mp4" -type f | wc -l
8

Darüber hinaus ls -lRkann als verwendet werdenfind .

Xiaodongjie
quelle
2

Du könntest es gebrauchen ls -1 *.mp4 | wc -l.

Dies listet alle Dateien auf .mp4, die auf enden , druckt jede Datei in einer neuen Zeile ( ls -1 *.mp4) und wcleitet die Ausgabe an, zu der die Anzahl der neuen Zeilen unter Verwendung des -lFlags gezählt wird.

Louis Matthijssen
quelle
Nicht sicher, warum dies abgelehnt wurde, es funktioniert
Panther
Da dies *.mp4von der Shell erweitert lswird, schlägt dies fehl, wenn .mp4das Verzeichnis so viele Dateien enthält, dass die Liste nicht lsals Argumente übergeben werden kann.
David Richerby
@Rmana Testen Sie es in einem Verzeichnis mit der Datei--.mp4
David Richerby
@DavidRicherby ja, du hast recht. --wird den zweiten Fall lösen; Ersteres führt zu einer Fehlermeldung (Sie benötigen viele Dateien!) und einer weiteren netten Frage. Eckfälle, aber es lohnt sich zu bemerken, ja.
Rmano
1
@Rmano Ohne Zugabe -qoder -bgehen diese nicht Zeilenumbrüche in den Dateinamen tolerieren. Wenn Sie laufen ls -1 *.mp4von Ihrem Terminal ohne Rohr, lssieht seine stdout ein Terminal und nimmt -qals implizierte, Druck ?s. Dieses Verhalten verschwindet jedoch, wenn der Ausgang weitergeleitet wird. ls -1 *.mp4 | wc -lüberzählt, wenn es Zeilenumbrüche gibt. ls -1 *.mp4 | catzeigt was wc"sieht". (Wird auch -1impliziert, wenn stdout kein Terminal ist, daher ist es optional.) Funktioniert ls -1q -- *.mp4 | wc -lfast, aber nicht mit null .mp4-Dateien.
Eliah Kagan
0

Dies sollte Ihnen die Liste der Dateien mit .mp4 geben

ls /path/to/directory | grep ".mp4$"

In Kombination mit erhalten wc -lSie Zählung

ls /path/to/directory | grep ".mp4$" | wc -l

Wenn die Suche Unterverzeichnisse enthalten soll

ls -lR /path/to/directory | grep ".mp4$" | wc -l
Back.Slash
quelle
zählt nicht
Panther
gab es mir bei der Verwendung mitwc -l
Back.Slash
Verwenden Sie ls ohne Pipe, um Ihre Antwort zu beschleunigen und zu verkürzen. Es wurde mindestens zweimal veröffentlicht.
Panther
@ bodhi.zazen ls /directory/*.mp4bewirkt, dass die Shell den Glob erweitert und so etwas ausführt. ls /directory/file1.mp4 /directory/file2.mp4 ...Dies schlägt fehl, wenn das Verzeichnis mehr mp4-Dateien enthält, als als Argumente übergeben werden können ls.
David Richerby
@ David Richby - es ist nicht mein ls Befehl, ich benutze find;)
Panther
0

In bash greift man kalt darauf zurück, Arrays mit glob zu verwenden:

$ files=( *.mp4  )
$ echo ${#files[@]}
30
Sergiy Kolodyazhnyy
quelle
0
ls | grep --count \.csv$

Ersetzen Sie (.csv mit der gewünschten Erweiterung)

Erläuterung: Ich denke, dass ein einfaches Schema darin besteht, die Liste der Dateien abzurufen und die Erweiterung mit grep zu zählen. \.Zuordnen .und $Anordnen der Erweiterung am Zeilenende. Dies funktioniert, weil bei der Ausgabe von ls ein Dateiname pro Zeile gesendet wird, den Sie überprüfen können, indem Sie Folgendes ausführen:

ls | cat
Mohsin Raza
quelle
1
Beachten Sie, dass Sie stattdessen grep --countauch verwenden könnten grep -c.
Mohsin Raza