281 votes

Calculer la taille d'un répertoire à l'aide de Python ?

Avant de réinventer cette roue particulière, quelqu'un a-t-il une routine sympa pour calculer la taille d'un répertoire en utilisant Python ? Ce serait très bien si la routine pouvait formater joliment la taille en Mb/Gb, etc.

16 votes

Ce ne serait PAS très agréable. Vous devriez avoir une fonction pour calculer la taille et une fonction tout à fait indépendante (qui pourrait être utilisée également avec les tailles de mémoire, par exemple) pour "formater joliment la taille en Mb/Gb etc".

20 votes

Oui je sais mais cela évite de poser deux questions.

3 votes

El tree sur les systèmes *nix fait tout cela gratuitement. tree -h -d --du /path/to/dir .

392voto

monkut Points 14549

Cette opération parcourt tous les sous-répertoires, en additionnant les tailles des fichiers :

import os

def get_size(start_path = '.'):
    total_size = 0
    for dirpath, dirnames, filenames in os.walk(start_path):
        for f in filenames:
            fp = os.path.join(dirpath, f)
            # skip if it is symbolic link
            if not os.path.islink(fp):
                total_size += os.path.getsize(fp)

    return total_size

print(get_size(), 'bytes')

Et un oneliner pour le plaisir en utilisant os.listdir ( N'inclut pas les sous-répertoires ) :

import os
sum(os.path.getsize(f) for f in os.listdir('.') if os.path.isfile(f))

Référence :

Mise à jour de Pour utiliser os.path.getsize Cette méthode est plus claire que l'utilisation de la méthode os.stat().st_size.

Merci à ghostdog74 de nous l'avoir signalé !

os.stat - st_size Donne la taille en octets. Peut également être utilisé pour obtenir la taille du fichier et d'autres informations relatives au fichier.

import os

nbytes = sum(d.stat().st_size for d in os.scandir('.') if d.is_file())

Mise à jour 2018

Si vous utilisez Python 3.4 ou une version antérieure, vous pouvez envisager d'utiliser l'option plus efficace walk fournie par la tierce partie scandir paquet. À partir de la version 3.5 de Python, ce paquetage a été intégré à la bibliothèque standard et à la bibliothèque de l'utilisateur. os.walk a reçu l'augmentation correspondante des performances.

Mise à jour 2019

Récemment, j'ai utilisé pathlib de plus en plus, voici un pathlib solution :

from pathlib import Path

root_directory = Path('.')
sum(f.stat().st_size for f in root_directory.glob('**/*') if f.is_file())

19 votes

+1 mais l'oneliner ne retourne pas un résultat valide car il n'est pas récursif

2 votes

Oui, c'est juste pour le cas du répertoire plat.

42 votes

Pour vous amuser, vous pouvez faire une taille récursive en une ligne : sum( os.path.getsize(os.path.join(dirpath,filename)) for dirpath, dirnames, filenames in os.walk( PATH ) for filename in filenames )

69voto

flaschbier Points 31

Certaines des approches suggérées jusqu'à présent mettent en œuvre une récursion, d'autres utilisent un shell ou ne produisent pas de résultats bien formatés. Lorsque votre code est unique pour les plateformes Linux, vous pouvez obtenir le formatage habituel, récursion incluse, en une seule ligne. A l'exception du print dans la dernière ligne, cela fonctionnera pour les versions actuelles de python2 y python3 :

du.py
-----
#!/usr/bin/python3
import subprocess

def du(path):
    """disk usage in human readable format (e.g. '2,1GB')"""
    return subprocess.check_output(['du','-sh', path]).split()[0].decode('utf-8')

if __name__ == "__main__":
    print(du('.'))

est simple, efficace et fonctionne pour les fichiers et les répertoires multi-niveaux :

$ chmod 750 du.py
$ ./du.py
2,9M

24 votes

Python, qui est multiplateforme par nature, devrait probablement éviter ce genre de situation.

15 votes

Merci pour ces remarques. J'ai ajouté une mise en garde concernant la dépendance à la plateforme dans la réponse. Cependant, une grande partie du code Python est constituée de scripts uniques. Un tel code ne devrait pas comporter des limitations fonctionnelles, des passages longs et sujets aux erreurs, ou des résultats peu communs dans les cas limites, juste pour des raisons de portabilité. au-delà de toute nécessité . Il s'agit, comme toujours, d'un compromis, et il incombe au développeur de faire un choix judicieux ;)

11 votes

Nitpick : pas Linux mais Unix/Posix spécifique :)

28voto

Samuel Lampa Points 1261

Voici une fonction récursive (elle additionne récursivement la taille de tous les sous-dossiers et de leurs fichiers respectifs) qui renvoie exactement les mêmes octets qu'en exécutant "du -sb ." sous linux (où le "." signifie "le dossier courant") :

import os

def getFolderSize(folder):
    total_size = os.path.getsize(folder)
    for item in os.listdir(folder):
        itempath = os.path.join(folder, item)
        if os.path.isfile(itempath):
            total_size += os.path.getsize(itempath)
        elif os.path.isdir(itempath):
            total_size += getFolderSize(itempath)
    return total_size

print "Size: " + str(getFolderSize("."))

3 votes

Cette fonction calcule aussi la taille du symlink - si vous voulez sauter les symlinks, vous devez vérifier que ce n'est pas cela : if os.path.isfile(itempath) and os.path.islink(itempath) and elif os.path.isdir(itempath) and os.path.islink(itempath).

12voto

troex Points 583

La réponse de monknut est bonne mais elle échoue sur un lien symbolique cassé, vous devez donc également vérifier si ce chemin existe vraiment

if os.path.exists(fp):
    total_size += os.stat(fp).st_size

3 votes

Vous ne voulez probablement pas suivre les liens symboliques. Vous devriez utiliser lstat .

9voto

Chris Points 398

La réponse acceptée ne prend pas en compte les liens matériels ou logiciels, et compterait ces fichiers deux fois. Il faudrait garder la trace des inodes que vous avez vus, et ne pas ajouter la taille de ces fichiers.

import os
def get_size(start_path='.'):
    total_size = 0
    seen = {}
    for dirpath, dirnames, filenames in os.walk(start_path):
        for f in filenames:
            fp = os.path.join(dirpath, f)
            try:
                stat = os.stat(fp)
            except OSError:
                continue

            try:
                seen[stat.st_ino]
            except KeyError:
                seen[stat.st_ino] = True
            else:
                continue

            total_size += stat.st_size

    return total_size

print get_size()

5 votes

Envisagez d'utiliser os.lstat (plutôt que os.stat ), ce qui évite de suivre les liens symboliques : docs.python.org/2/library/os.html#os.lstat

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X