Question

Je souhaite obtenir une liste des dossiers du niveau actuel (sans compter leurs sous-dossiers) et simplement imprimer le nom du dossier et le nombre de fichiers qu'il contient (de préférence en filtrant au format * .jpg).

Est-ce possible dans le shell bash standard? ls -l imprime à peu près tout sauf le nombre de fichiers:)

Était-ce utile?

La solution

Je suis venu avec celui-ci:

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

Supprimez le deuxième -maxdepth 1 si la recherche dans les répertoires de fichiers jpg doit être récursive en considérant les sous-répertoires. Notez que cela ne prend en compte que le nom des fichiers. Vous pouvez renommer un fichier en cachant qu'il s'agit d'une image au format jpg. Vous pouvez utiliser la commande fichier pour deviner le contenu, au lieu de cela (maintenant, recherche également de manière récursive):

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

Cependant, cela est beaucoup plus lent, car il doit lire une partie des fichiers et éventuellement interpréter ce qu'ils contiennent (s'il a de la chance, il trouve un identifiant magique au début du fichier). -mindepth 1 l'empêche d'imprimer . (le répertoire en cours) en tant que répertoire supplémentaire dans lequel il effectue la recherche.

Autres conseils

J'ai trouvé cette question après avoir déjà réalisé mon propre script similaire. Il semble correspondre à vos conditions et est très flexible, alors je me suis dit que je l’ajouterais comme réponse.

Avantages:

  • peut être regroupé dans n'importe quelle profondeur (0 pour . , 1 pour les sous-répertoires du premier niveau, etc.)
  • imprime une jolie sortie
  • pas de boucle et une seule commande find , donc un peu plus rapide sur les grands répertoires
  • peut toujours être ajusté pour ajouter des filtres personnalisés (maxdepth pour le rendre non récursif, modèle de nom de fichier)

Code brut:

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

Enveloppé dans une fonction et expliqué:

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
}

Produit une sortie comme ceci:

$ fc 0
1668 .

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

Bien sûr, avec le numéro en premier, il peut être redirigé vers sort :

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

mine est plus rapide à taper à partir de la ligne de commande. :)

Les autres suggestions offrent-elles un avantage réel par rapport aux propositions suivantes?

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 "\.<*>quot;`; do
echo $dir
ls $dir/*.jpg | wc -l
done;

Vous pouvez le faire sans commandes externes:

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

Vous pouvez également utiliser awk ( nawk ou / usr / xpg4 / bin / awk sur Solaris ). :

printf "%s\n" */*jpg |
  awk -F\/ 'END { 
    for (d in _) 
      print d ":",_[d] 
      }
  { _[$1]++ }'
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top