Anzahl der Dateien in jedem Unterverzeichnis

21

Ich möchte, dass ein BASH-Befehl nur die Anzahl der Dateien in jedem Unterverzeichnis eines Verzeichnisses auflistet.

ZB im Verzeichnis /tmpgibt es dir1, dir2... würde ich gerne sehen:

`dir1` : x files 
`dir2` : x files ...
jldupont
quelle

Antworten:

32

Angenommen, Sie möchten nur eine rekursive Anzahl von Dateien, keine Verzeichnisse und andere Typen, dann sollte so etwas funktionieren:

find . -maxdepth 1 -mindepth 1 -type d | while read dir; do
  printf "%-25.25s : " "$dir"
  find "$dir" -type f | wc -l
done
Thor
quelle
Außerdem erhalte ich "find: warning: Sie haben die Option -maxdepth nach einem Nicht-Optionsargumenttyp angegeben, aber die Optionen sind nicht positionell (-maxdepth wirkt sich sowohl auf die zuvor angegebenen als auch auf die danach angegebenen Tests aus. Bitte geben Sie Optionen an vor anderen Argumenten. "
Jldupont
2
Beide bisher gegebenen Antworten führen zu falschen Ergebnissen in dem unwahrscheinlichen Fall, dass es Dateien gibt, deren Namen Zeilenumbrüche enthalten. Sie können das mit einem find... -print0 | xargs -0....
Scott
@jldupont: Verschiebe die Tiefenargumente vor den ´-Typ d´, ich habe die Antwort bearbeitet.
Thor
Ja, und lassen Sie mich die Information hinzufügen, dass diese hervorragende Lösung keine externen Variablen akzeptiert und daher funktioniert bash alias!!
Syntaxfehler
schnell und Rohrleitungen erhalten sort -rn -k 2,2 -t$':'Sie die DESC-Liste
Andre Figueiredo
14

Diese Aufgabe faszinierte mich so sehr, dass ich selbst eine Lösung finden wollte. Es ist nicht einmal eine while - Schleife nehmen und KANN schneller in der Ausführungsgeschwindigkeit. Unnötig zu erwähnen, dass Thors Bemühungen mir sehr geholfen haben, die Dinge im Detail zu verstehen.

Also hier ist meins:

find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "{} : $(find "{}" -type f | wc -l)" file\(s\)' \;

Es sieht aus einem bestimmten Grund bescheiden aus, weil es viel mächtiger ist als es aussieht. :-)

Wenn Sie dies jedoch in Ihre .bash_aliasesDatei aufnehmen möchten, muss dies folgendermaßen aussehen:

alias somealias='find . -maxdepth 1 -mindepth 1 -type d -exec sh -c '\''echo "{} : $(find "{}" -type f | wc -l)" file\(s\)'\'' \;'

Beachten Sie die sehr schwierige Behandlung verschachtelter einfacher Anführungszeichen. Und nein, es ist nicht möglich, doppelte Anführungszeichen für das sh -cArgument zu verwenden.

Syntax-Fehler
quelle
Es ist langsamer, da es für jedes Verzeichnis / bin / sh aufruft. Sie können dies mit überprüfen strace -fc script. Ihre Version macht ungefähr 70% mehr Systemaufrufe. +1 für kürzeren Code :-)
Thor
1
inspiriert davon; sortiert nach Filecount:find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "$(find "{}" -type f | wc -l)" {}' \; | sort -nr
Mnagel
7
find . -type f | cut -d"/" -f2 | uniq -c

Listet einen Ordner und Dateien im aktuellen Ordner mit einer Anzahl von Dateien auf, die darunter gefunden werden. Schnelle und nützliche IMO. (Dateien werden mit Anzahl 1 angezeigt).

Nein, danke
quelle
1
Wie wäre es mit einer kleinen Erklärung, wie es funktioniert? :)
C0deDaedalus
1
super, danke! Möglicherweise möchten Sie hinzufügen | sort -rn, um Unterverzeichnisse nach Anzahl der Dateien zu sortieren.
Dennis Golomazov
1

Die Verwendung von find ist definitiv der richtige Weg, wenn Sie rekursiv zählen möchten, aber nur die Dateien direkt unter einem bestimmten Verzeichnis zählen möchten:

ls dir1 | wc -l

jrajav
quelle
Ich möchte dies nicht für jedes der 1000 Verzeichnisse tun, die ich dort habe ...
jldupont
Verwenden Sie dann xargs. ls -d */ | xargs -n1 ls | wc -l(Verwenden Sie die Antwort, die Sie akzeptiert haben, wenn es bereits funktioniert! Dies ist nur und jetzt wissen Sie.)
jrajav
Ihr Vorschlag zeigte in vielen Sekunden keine Ergebnisse, während die Antwort, die ich akzeptierte, dies tat.
Jldupont
@ jrajav Dieser Ansatz schlägt bei Verzeichnissen mit Leerzeichen absolut fehl. Deshalb findist es so wichtig. (geschweige denn -print0und xargs -0, bereits von Scott in der anderen Antwort darauf hingewiesen)
Syntaxfehler
1
find . -mindepth 1 -type d -print0 | xargs -0 -I{} sh -c 'printf "%4d : %s\n" "$(find {} -type f | wc -l)" "{}"'

Ich muss oft die Anzahl der Dateien in meinen Unterverzeichnissen zählen und diesen Befehl verwenden. Ich bevorzuge, dass die Zählung zuerst erscheint.

Teddy Katayama
quelle
0

Was ich benutze ... Dadurch wird ein Array aller Unterverzeichnisse in dem von Ihnen als Parameter angegebenen erstellt. Drucken Sie das Unterverzeichnis und die Anzahl desselben Unterverzeichnisses, bis alle Unterverzeichnisse verarbeitet sind.

#!/bin/bash    
directories=($(/bin/ls -l $1 | /bin/grep "^d" | /usr/bin/awk -F" " '{print $9}'))

for item in ${directories[*]}
    do
        if [ -d "$1$item" ]; then
            echo "$1$item"
            /bin/ls $1$item | /usr/bin/wc -l
        fi
    done
derberlinersmurf
quelle
0

Sie könnten diesen Python-Code verwenden. Starten Sie den Interpreter, indem Sie Folgendes python3ausführen und einfügen:

folder_path = '.'
import os, glob
for folder in sorted(glob.glob('{}/*'.format(folder_path))):
    print('{:}: {:>8,}'.format(os.path.split(folder)[-1], len(glob.glob('{}/*'.format(folder)))))

Oder eine rekursive Version für verschachtelte Zählungen:

import os, glob
def nested_count(folder_path, level=0):
    for folder in sorted(glob.glob('{}/'.format(os.path.join(folder_path, '*')))):
        print('{:}{:}: {:,}'.format('    '*level, os.path.split(os.path.split(folder)[-2])[-1], len(glob.glob(os.path.join(folder, '*')))))
        nested_count(folder, level+1)
nested_count('.')

Beispielausgabe:

>>> figures: 5
>>> misc: 1
>>> notebooks: 5
>>>     archive: 65
>>>     html: 12
>>>     py: 12
>>>     src: 14
>>> reports: 1
>>>     content: 6
>>> src: 1
>>>     html_download: 1
AlexG
quelle