31 votes

Nombre de fichiers dans chaque sous-répertoire

Je voudrais une commande BASH pour lister seulement le nombre de fichiers dans chaque sous-répertoire d'un répertoire.

Par exemple, dans le répertoire /tmp il y a dir1 , dir2 , ... J'aimerais voir :

`dir1` : x files 
`dir2` : x files ...

0voto

Alex Points 351

Vous pouvez utiliser ce code Python. Démarrez l'interpréteur en exécutant python3 et collez ceci :

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)))))

Ou une version récursive pour les comptages imbriqués :

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('.')

Exemple de sortie :

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

0voto

Kamil Maciorowski Points 57004

Pour des méthodes fiables de comptage des fichiers dans un répertoire, voir ma réponse : Quel est un code fiable pour compter les fichiers ?

Dans votre cas, nous devons en plus itérer sur les sous-répertoires. A for La boucle est bonne pour cela :

for d in */; do
    c="$(cd -- "$d" && find . ! -name . -exec printf a \; | wc -c)"
    if [ "$?" -ne 0 ]; then c="?"; fi
    printf '%-25s : %s\n' "${d%/}" "$c"
done

Notes :

  • Normalement */ ne correspond pas aux répertoires dont le nom commence par un point (répertoires "cachés"). En Bash shopt -s dotglob change ça.

  • ! -name . est responsable de ne pas compter le sous-répertoire respectif lui-même.

  • ${d%/} supprime la queue / . Si nous avons utilisé * au lieu de */ dans le for il n'y aurait alors rien à supprimer, mais la boucle itèrerait également sur les non-répertoires.

  • Double tiret ( -- ) est utile dans le cas où un nom commence par - . Si nous avons utilisé ./*/ dans le for alors il n'y aurait pas besoin de -- mais vous voudrez probablement supprimer le début de l'expression ./ tout en imprimant la sortie, cela compliquerait le code.

  • Dans la sortie ? apparaît en cas de problème. Défaillant cd (probablement en raison de permissions insuffisantes) est le problème que j'avais en tête. find L'impossibilité de descendre dans un (sous- )sous-répertoire ne constitue pas un problème dans ce contexte. Si vous voyez un numéro, cela signifie find a trouvé autant de fichiers là, donc il y a au moins autant de fichiers dans le répertoire. Si vous voyez ? alors cela signifie find n'a probablement pas couru parce que cd avait échoué.

  • Voir le réponse déjà liée il vous aidera à adapter le find à vos besoins (par exemple, solution non récursive, comptage des fichiers d'un type spécifique, certaines optimisations).

  • Les caractères multi-octets dans les noms prêtent à confusion printf et la sortie peut sembler mal alignée.

  • Le format qui imprime les noms est %-25s Ainsi, tout nom est imprimé tel quel (avec un remplissage). Les caractères de nouvelle ligne, les caractères de retour chariot, les séquences d'échappement dans les noms peuvent provoquer des résultats inattendus. Avec printf builtin dans l'utilisation de Bash %q au lieu de %s (il sera %-25q dans notre cas) pour atténuer le problème.

-1voto

Ce que j'utilise... Ceci fait un tableau de tous les sous-répertoires dans celui que vous donnez en paramètre. Imprime le sous-répertoire et le nombre de ce même sous-répertoire jusqu'à ce que tous les sous-répertoires soient traités.

#!/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

-1voto

Ronen Tal Points 1

Sortie au format csv pour les dossiers :

for f in $(find * -type d); do echo $f,$(ls ./$f | wc -l) ; done

sortie :

aFolder,30

bFolder,20

cFolder,10

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X