Frage

ich eine Liste von Ordnern auf dem aktuellen Niveau erhalten mag (nicht deren Unterordner einschließlich) und einfach auf die Ordnernamen und eine Zählung der Anzahl der Dateien im Ordner (vorzugsweise * .jpg wenn möglich Filterung) drucken.

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

War es hilfreich?

Lösung

Ich habe mit diesem kommen:

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

Lassen Sie die zweite -maxdepth 1 wenn die Suche in den Verzeichnissen für jpg-Dateien rekursiv Berücksichtigung Unterverzeichnisse sein sollte. Beachten Sie, dass die nur die Namen der Dateien berücksichtigt. Sie könnten eine Datei umbenennen, versteckt, dass es ein jpg Bild. Sie können den file Befehl verwenden, um eine Vermutung über den Inhalt zu tun, statt (jetzt auch sucht 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 interpretieren, was sie enthalten (wenn sie Glück hat, findet es eine magische ID am Anfang der Datei). Die -mindepth 1 verhindert, dass Druck . (das aktuelle Verzeichnis) als ein anderes Verzeichnis, das er sucht.

Andere Tipps

Ich fand diese Frage, nachdem ich schon dachte, würde mein eigenes ähnliches Skript aus. Es scheint, Ihre Bedingungen zu passen und ist sehr flexibel, so dass ich dachte, dass ich es als Antwort hinzufügen würde.

Vorteile:

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

Raw Code:

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

Wrapped in eine Funktion 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 sort geleitet werden:

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

Mine ist schneller von der Kommandozeile eingeben. :)

Sie die anderen Vorschläge einen wirklichen Vorteil gegenüber der folgenden anbieten?

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


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

Sie können es ohne externe Befehle tun:

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

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

printf "%s\n" */*jpg |
  awk -F\/ 'END { 
    for (d in _) 
      print d ":",_[d] 
      }
  { _[$1]++ }'
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top