Unix-Befehl Ordner mit Datei zählt zur Liste
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:)
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]++ }'