2009-03-10 4 views
17

Ich möchte eine Liste von Ordnern auf der aktuellen Ebene (ohne ihre Unterordner) abrufen und einfach den Ordnernamen und die Anzahl der Dateien im Ordner (vorzugsweise filtern nach * .jpg wenn möglich).UNIX-Befehl zum Auflisten von Ordnern mit Dateianzahl

Ist dies in der Standard-Bash-Shell möglich? ls -l druckt über alles, aber die Datei zählen :)

+2

Um die Person, die enge Abstimmung: bash ist eine tatsächliche Sprache . – Bernard

Antwort

21

ich mit diesem habe kommen:

find -maxdepth 1 -type d | while read dir; do 
    count=$(find "$dir" -maxdepth 1 -iname \*.jpg | wc -l) 
    echo "$dir ; $count" 
done 

Tropfen der zweite -maxdepth 1 wenn die Suche in den Verzeichnissen für jpg-Dateien rekursiv sein sollten Unterverzeichnisse unter Berücksichtigung . Beachten Sie, dass nur der Name der Dateien berücksichtigt wird. Sie könnten eine Datei umbenennen und verbergen, dass es sich um ein JPG-Bild handelt. Sie können den file Befehl verwenden, um eine Vermutung über den Inhalt zu tun, statt (jetzt sucht auch rekursiv):

find -mindepth 1 -maxdepth 1 -type d | while read dir; do 
    count=$(find "$dir" -type f | xargs file -b --mime-type | 
      grep 'image/jpeg' | wc -l) 
    echo "$dir ; $count" 
done 

Das ist jedoch viel langsamer, da es Teil der Dateien zu lesen hat und schließlich zu interpretieren, was sie enthalten (wenn es Glück hat, findet es eine magische ID am Anfang der Datei). Das -mindepth 1 verhindert, dass es . (das aktuelle Verzeichnis) als ein anderes Verzeichnis, das es durchsucht, druckt.

1
#!/bin/bash 
for dir in `find . -type d | grep -v "\.$"`; do 
echo $dir 
ls $dir/*.jpg | wc -l 
done; 
8

ich kann schneller über die Befehlszeile eingeben. :)

bieten die anderen Vorschläge einen wirklichen Vorteil gegenüber den folgenden?

find -name '*.jpg' | wc -l    # recursive 


find -maxdepth 1 -name '*.jpg' | wc -l # current directory only 
+0

Beispiel: Lehrer möchte jpg Bilder seiner Schüler auflisten. also legt er den Befehl in/home und will alle jpg in diesen Unterverzeichnissen auflisten, um zu bestätigen, dass sie einige *** Dinge nicht enthalten :) Beispiel meines vorherigen Unix-Lehrers. er wusste wovon er sprach: ppls versuchten ihre pr0n in bin dateien zu verstecken: D –

+0

Das druckt nur die Gesamtzahl der Dateien, nicht die Anzahl pro Ordner. Ich habe es jetzt trotzdem getan und folge dem obigen Kommentar. – DisgruntledGoat

+0

@DisgruntledGoat, ich habe deine Frage falsch gelesen. Das tut mir leid. Ich verstehe jetzt. – m42

1

Sie tun können, er kann ohne externe Befehle:

for d in */; do 
    set -- "$d"*.jpg 
    printf "%s: %d\n" "${d%/}" "$#" 
done 

Oder Sie können awk (nawk oder /usr/xpg4/bin/awk auf Solaris) verwenden:

9

Ich habe diese Frage afte gefunden Ich hatte bereits mein eigenes ähnliches Skript herausgefunden. Es scheint zu Ihren Bedingungen zu passen und ist sehr flexibel, also dachte ich, dass ich es als Antwort hinzufügen würde.

Vorteile:

  • können jede Tiefe (0 für ., 1 für die erste Ebene Verzeichnisse gruppiert werden, usw.)
  • druckt ziemlich Ausgabe
  • keine Schleife, und nur ein find Befehl, so dass es ein bisschen schneller auf großen Verzeichnissen ist
  • noch abgestimmt werden können benutzerdefinierte Filter (maxdepth, um es nicht-rekursive, Dateinamensmuster hinzufügen
  • )

Raw Code:

find -P . -type f | rev | cut -d/ -f2- | rev | \ 
     cut -d/ -f1-2 | cut -d/ -f2- | sort | uniq -c 

in eine Funktion eingewickelt und erklärt:

fc() { 
    # Usage: fc [depth >= 0, default 1] 
    # 1. List all files, not following symlinks. 
    #  (Add filters like -maxdepth 1 or -iname='*.jpg' here.) 
    # 2. Cut off filenames in bulk. Reverse and chop to the 
    #  first/(remove filename). Reverse back. 
    # 3. Cut everything after the specified depth, so that each line 
    #  contains only the relevant directory path 
    # 4. Cut off the preceeding '.' unless that's all there is. 
    # 5. Sort and group to unique lines with count. 

    find -P . -type f \ 
     | rev | cut -d/ -f2- | rev \ 
     | cut -d/ -f1-$((${1:-1}+1)) \ 
     | cut -d/ -f2- \ 
     | sort | uniq -c 
} 

Erzeugt eine Ausgabe wie folgt aus:

$ fc 0 
1668 . 

$ fC# depth of 1 is default 
    6 . 
    3 .ssh 
    11 Desktop 
    44 Downloads 
1054 Music 
550 Pictures 

Natürlich mit der Nummer ersten kann es zu sort geleitet werden:

$ fc | sort 
    3 .ssh 
    6 . 
    11 Desktop 
    44 Downloads 
550 Pictures 
1054 Music 
+0

Unter Solaris ist keine 'rev' verfügbar. Sie können stattdessen 'perl' als universelle Lösung verwenden: ' find -P. -type f | perl -lpe '$ _ = rückwärts' | geschnitten -d/-f2- | perl -lpe '$ _ = rückwärts' | Schnitt -d/-f1-2 | geschnitten -d/-f2- | sortieren | uniq -c' –