it-swarm.com.de

Wie zählt man die Anzahl der Dateien in jedem Verzeichnis?

Ich kann alle Verzeichnisse nach auflisten

find ./ -type d

Ich habe versucht, den Inhalt jedes Verzeichnisses aufzulisten und die Anzahl der Dateien in jedem Verzeichnis mithilfe des folgenden Befehls zu zählen

find ./ -type d | xargs ls -l | wc -l

Dies summierte jedoch die Gesamtzahl der Zeilen, die von zurückgegeben wurden

find ./ -type d | xargs ls -l

Gibt es eine Möglichkeit, die Anzahl der Dateien in jedem Verzeichnis zu zählen?

69
user784637

Angenommen, Sie haben GNU gefunden, lassen Sie die Verzeichnisse finden und lassen Sie den Rest von bash erledigen:

find . -type d -print0 | while read -d '' -r dir; do
    files=("$dir"/*)
    printf "%5d files in directory %s\n" "${#files[@]}" "$dir"
done
78
glenn jackman

Dadurch wird die Dateianzahl pro Verzeichnis für die aktuelle Verzeichnisebene gedruckt:

du -a | cut -d/ -f2 | sort | uniq -c | sort -nr
105

Sie können nach allen Dateien suchen, die Dateinamen entfernen, eine Zeile mit nur dem Verzeichnisnamen für jede Datei lassen und dann zählen, wie oft jedes Verzeichnis angezeigt wird:

find . -type f |
sed 's%/[^/]*$%%' |
sort |
uniq -c

Das einzige Problem dabei ist, wenn Sie Dateinamen oder Verzeichnisnamen mit einem Zeilenvorschubzeichen haben, was ziemlich unwahrscheinlich ist. Wenn Sie sich wirklich um Zeilenumbrüche in Dateinamen oder Verzeichnisnamen kümmern müssen, schlage ich vor, dass Sie sie finden und korrigieren, damit sie keine Zeilenumbrüche enthalten (und den Schuldigen in Ruhe vom Fehler ihrer Wege überzeugen).


Wenn Sie an der Anzahl der Dateien in jedem Unterverzeichnis des aktuellen Verzeichnisses interessiert sind und alle Dateien in beliebigen Unterverzeichnissen zusammen mit den Dateien im unmittelbaren Unterverzeichnis zählen, würde ich den Befehl sed zum Drucken anpassen nur das oberste Verzeichnis:

find . -type f |
sed -e 's%^\(\./[^/]*/\).*$%\1%' -e 's%^\.\/[^/]*$%./%' |
sort |
uniq -c

Das erste Muster erfasst den Anfang des Namens, den Punkt, den Schrägstrich, den Namen bis zum nächsten Schrägstrich und den Schrägstrich und ersetzt die Zeile durch nur den ersten Teil.

./dir1/dir2/file1

wird ersetzt durch

./dir1/

Die zweite Ersetzung erfasst die Dateien direkt im aktuellen Verzeichnis. Sie haben am Ende keinen Schrägstrich, und diese werden durch ./ ersetzt. Die Sortierung und Zählung funktioniert dann nur für die Anzahl der Namen. 

12

Hier ist eine Möglichkeit, dies zu tun, aber wahrscheinlich nicht die effizienteste.

find -type d -print0 | xargs -0 -n1 bash -c 'echo -n "$1:"; ls -1 "$1" | wc -l' --

Gibt eine Ausgabe wie folgt aus, mit dem Verzeichnisnamen gefolgt von der Anzahl der Einträge in diesem Verzeichnis. Beachten Sie, dass der Ausgabezähler auch Verzeichniseinträge enthält, die möglicherweise nicht Ihren Vorstellungen entsprechen.

./c/fa/l:0
./a:4
./a/c:0
./a/a:1
./a/a/b:0
11
Austin Phillips

Die Lösung aller anderen hat den einen oder anderen Nachteil.

find -type d -readable -exec sh -c 'printf "%s " "$1"; ls -1UA "$1" | wc -l' sh {} ';'

Erläuterung:

  • -type d: Wir sind an Verzeichnissen interessiert.
  • -readable: Wir wollen sie nur, wenn möglich die Dateien darin auflistet. Beachten Sie, dass find immer noch einen Fehler ausgibt, wenn versucht wird, nach weiteren Verzeichnissen zu suchen. Dies verhindert jedoch, dass -exec aufgerufen wird.
  • -exec sh -c BLAH sh {} ';': Führen Sie für jedes Verzeichnis dieses Skriptfragment aus, wobei $0 auf sh und $1 auf den Dateinamen gesetzt ist.
  • printf "%s " "$1": portabel und minimal den Verzeichnisnamen, gefolgt von nur einem Leerzeichen, nicht einem Zeilenvorschub.
  • ls -1UA: Listet die Dateien (eine pro Zeile) in der Reihenfolge des Verzeichnisses auf (um ein Stehenbleiben der Pipe zu vermeiden), ausschließlich only die speziellen Verzeichnisse . und ...
  • wc -l: Zählen Sie die Zeilen
7
o11c

Dies kann auch durch Schleifen über ls anstelle von find erfolgen

for f in */; do echo "$f -> $(ls $f | wc -l)"; done

Erläuterung:

for f in */; - Schleife über alle Verzeichnisse

do echo "$f -> - druckt jeden Verzeichnisnamen aus

$(ls $f | wc -l) - rufe ls für dieses Verzeichnis auf und zähle die Zeilen

4
Sixhobbits

Leicht modifizierte Version von Sebastians antwort mit find anstelle von du (um den mit der Dateigröße verbundenen Aufwand auszuschließen, den du ausführen muss und der niemals verwendet wird)

 find ./ -mindepth 2 -type f | cut -d/ -f2 | sort | uniq -c | sort -nr

Der -mindepth 2-Parameter wird verwendet, um Dateien im aktuellen Verzeichnis auszuschließen. Wenn Sie es entfernen, sehen Sie eine Reihe von Zeilen wie folgt:

  234 dir1
  123 dir2
    1 file1
    1 file2
    1 file3
      ...
    1 fileN

(Ähnlich wie bei der du-basierten Variante)

Wenn Sie auch die Dateien im aktuellen Verzeichnis zählen müssen, verwenden Sie diese erweiterte Version:

{ find ./ -mindepth 2 -type f | cut -d/ -f2 | sort && find ./ -maxdepth 1 -type f | cut -d/ -f1; } | uniq -c | sort -nr

Die Ausgabe sieht wie folgt aus:

  234 dir1
  123 dir2
   42 .
2
Yoory N.

finden . -type f -printf '% h\n' | sortieren | uniq -c

gibt zum Beispiel:

  5 .
  4 ./aln
  5 ./aln/iq
  4 ./bs
  4 ./ft
  6 ./hot
1
Giddy

Dies sollte den Verzeichnisnamen gefolgt von der Anzahl der Dateien im Verzeichnis zurückgeben.

findfiles() {
    echo "$1" $(find "$1" -maxdepth 1 -type f | wc -l)
}

export -f findfiles

find ./ -type d -exec bash -c 'findfiles "$0"' {} \;

Beispielausgabe:

./ 6
./foo 1
./foo/bar 2
./foo/bar/bazzz 0
./foo/bar/baz 4
./src 4

export -f ist erforderlich, da das -exec-Argument von find die Ausführung einer Bash-Funktion nicht zulässt, sofern Sie die Bash nicht explizit aufrufen und die im aktuellen Bereich definierte Funktion explizit in die neue Shell exportieren müssen.

1
Tuxdude

Ich lebe dies hier für eine zukünftige Erinnerung

ls |parallel 'echo {} && ls {}|wc -l'
1
emanuele

Dies gibt die Gesamtzahl an.

for file in */; do echo "$file -> $(ls $file | wc -l)"; done | cut -d ' ' -f 3| py --ji -l 'numpy.sum(l)'

Ein superschneller Wunderbefehl, der Dateien rekursiv durchläuft, um die Anzahl der Bilder in einem Verzeichnis zu zählen und die Ausgabe nach Bilderweiterung zu organisieren:

find . -type f | sed -e 's/.*\.//' | sort | uniq -c | sort -n | grep -Ei '(tiff|bmp|jpeg|jpg|png|gif)$'

Credits: https://unix.stackexchange.com/a/386135/35498

0
tsveti_iko

Ich kombinierte die Antwort von @glenn jackman und @ pcarvalho (in der Kommentarliste stimmt die Antwort von pcarvalho nicht, weil die zusätzliche Stilsteuerungsfunktion des Zeichens '`' (Backtick)).

Mein Skript kann Pfad als Augment akzeptieren und die Verzeichnisliste als ls -l sortieren. Außerdem kann es das Problem "Platz im Dateinamen" lösen.

#!/bin/bash
OLD_IFS="$IFS"
IFS=$'\n'
for dir in $(find $1 -maxdepth 1 -type d | sort); 
do
    files=("$dir"/*)
    printf "%5d,%s\n" "${#files[@]}" "$dir"
done
FS="$OLD_IFS"

Meine erste Antwort in stackoverflow, und ich hoffe, es kann Ihnen helfen

0
vacing

Einfache Möglichkeit, Dateien eines bestimmten Typs rekursiv zu finden. In diesem Fall .jpg-Dateien für alle Ordner im aktuellen Verzeichnis:

find . -name *.jpg -print | wc -l

0
Rex Barker

Ich habe es mit einigen der anderen hier versucht, endete aber mit Unterordnern, die in der Dateizählung enthalten waren, als ich nur die Dateien wollte. Dies gibt ./folder/path<tab>nnn mit der Anzahl der Dateien für jeden Unterordner im aktuellen Ordner aus, nicht jedoch Unterordner.

for d in `find . -type d -print` 
do 
  echo -e "$d\t$(find $d -maxdepth 1 -type f -print | wc -l)"
done
0
sthames42
find . -type f | cut -d/ -f2 | sort | uniq -c
  • find. -type f, um alle Elemente der Typdatei zu finden
  • cut -d/ -f2, um den jeweiligen Ordner auszuschneiden
  • sort, um die Liste der Ordnernamen zu sortieren
  • uniq -c, um zurückzugeben, wie oft jeder Ordnername gezählt wurde
0
DCZ