Calculer la taille d'un répertoire en utilisant Python?
194
Avant de réinventer cette roue particulière, est-ce que quelqu'un a une bonne routine pour calculer la taille d'un répertoire en utilisant Python? Ce serait très bien si la routine formaterait bien la taille en Mo / Go, etc.
Ce ne serait PAS très agréable. Vous devriez avoir une fonction pour calculer la taille et une fonction assez indépendante (qui pourrait être utilisée aussi avec des tailles de mémoire, par exemple) pour "formater la taille bien en Mb / Gb etc".
John Machin
17
Oui je sais mais cela évite de poser deux questions.
Gary Willoughby
2
La treecommande sur les systèmes * nix fait tout cela gratuitement. tree -h -d --du /path/to/dir.
meh
@mehdu -sh /path/to/dir/*
mrgloom
Réponses:
272
Cela parcourt tous les sous-répertoires; sommation des tailles de fichier:
import os
defget_size(start_path = '.'):
total_size = 0for dirpath, dirnames, filenames in os.walk(start_path):
for f in filenames:
fp = os.path.join(dirpath, f)
# skip if it is symbolic linkifnot os.path.islink(fp):
total_size += os.path.getsize(fp)
return total_size
print(get_size(), 'bytes')
Et un oneliner pour s'amuser 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))
Mise
à jour Pour utiliser os.path.getsize , c'est plus clair que d'utiliser la méthode os.stat (). St_size.
Merci à ghostdog74 pour 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 la walkméthode la plus efficace fournie par le scandirpackage tiers . Dans Python 3.5 et versions ultérieures, ce package a été incorporé dans la bibliothèque standard et os.walka reçu l'augmentation correspondante des performances.
Mise à jour 2019
Récemment, j'utilise de pathlibplus en plus, voici une pathlibsolution:
from pathlib import Path
root_directory = Path('.')
sum(f.stat().st_size for f in root_directory.glob('**/*') if f.is_file())
+1 mais le oneliner ne renvoie pas de résultat valide car il n'est pas récursif
luc
2
Ouais, c'est juste pour le cas de répertoire plat.
monkut
38
Pour vous amuser vraiment, vous pouvez faire une taille récursive sur une ligne: sum (os.path.getsize (os.path.join (dirpath, filename)) pour dirpath, dirnames, noms de fichiers dans os.walk (PATH) pour le nom de fichier dans les noms de fichiers)
driax
2
Mais vous devez utiliser st_sizesi vous ne voulez pas suivre les liens symboliques, comme vous devriez alors utiliser lstat.
asmeurer
3
Attention! ce n'est pas la même chose que «du -sb». Voir la réponse de Samuel Lampa! Votre code ignore la taille du dossier utilisé pour stocker FAT.
Yauhen Yakimovich
48
Certaines des approches suggérées jusqu'à présent implémentent une récursivité, d'autres utilisent un shell ou ne produiront pas de résultats parfaitement formatés. Lorsque votre code est unique pour les plates-formes Linux, vous pouvez obtenir le formatage comme d'habitude, récursivité incluse, en une seule ligne. À l'exception de la printdernière ligne, il fonctionnera pour les versions actuelles de python2et python3:
du.py
-----
#!/usr/bin/python3import subprocess
defdu(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 fonctionnera pour les fichiers et les répertoires à plusieurs niveaux:
Python, étant de nature multiplateforme, devrait probablement éviter cela
Jonathan
11
Merci pour ces remarques. J'ai ajouté une mise en garde concernant la dépendance de la plate-forme à la réponse. Cependant, une grande partie du code Python est un script unique. Un tel code ne doit pas être accompagné de limitations fonctionnelles, de passages longs et sujets aux erreurs, ou de résultats inhabituels dans les cas extrêmes, juste pour une portabilité au-delà de tout besoin . C'est, comme toujours, un compromis, et il est de la responsabilité du développeur de choisir judicieusement;)
flaschbier
9
Nitpick: pas Linux mais spécifique Unix / Posix :)
Mr Shark
3
Il est probablement judicieux d'ajouter l'option '-x' à la commande du afin de limiter la recherche au système de fichiers. En d'autres termes, utilisez plutôt ['du', '-shx', path].
Keith Hanlan
24
Voici une fonction récursive (elle résume récursivement la taille de tous les sous-dossiers et de leurs fichiers respectifs) qui renvoie exactement les mêmes octets que lors de l'exécution de "du -sb". sous linux (où le "." signifie "le dossier actuel"):
import os
defgetFolderSize(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("."))
Cette fonction calcule également la taille du lien symbolique - si vous voulez ignorer les liens symboliques, vous devez vérifier que ce n'est pas cela: if os.path.isfile (itempath) et os.path.islink (itempath) et elif os.path.isdir ( itempath) et os.path.islink (itempath).
airween
19
Taille du dossier récursif Python 3.5 en utilisant os.scandir
deffolder_size(path='.'):
total = 0for entry in os.scandir(path):
if entry.is_file():
total += entry.stat().st_size
elif entry.is_dir():
total += folder_size(entry.path)
return total
Méthode Python 3 one-liner si vous ne vous inquiétez pas de la récursivité sum([entry.stat().st_size for entry in os.scandir(file)]). La sortie de note est en octets, / 1024 pour obtenir Ko et / (1024 * 1024) pour obtenir Mo.
weiji14
5
@ weiji14 Perdez les crochets, c'est-à-dire sum(entry.stat().st_size for entry in os.scandir(file)). Aucune raison de faire une liste, car sumprend également des itérateurs.
Vedran Šego
9
La réponse 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
Vous ne souhaitez probablement pas suivre les liens symboliques. Vous devriez utiliser lstat.
asmeurer
8
La réponse acceptée ne prend pas en compte les liens physiques ou logiciels et compterait ces fichiers deux fois. Vous voudrez garder une trace des inodes que vous avez vus et ne pas ajouter la taille de ces fichiers.
import os
defget_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:
continuetry:
seen[stat.st_ino]
except KeyError:
seen[stat.st_ino] = Trueelse:
continue
total_size += stat.st_size
return total_size
print get_size()
La réponse de Chris est bonne mais pourrait être rendue plus idiomatique en utilisant un ensemble pour vérifier les répertoires vus, ce qui évite également d'utiliser une exception pour le flux de contrôle:
defdirectory_size(path):
total_size = 0
seen = set()
for dirpath, dirnames, filenames in os.walk(path):
for f in filenames:
fp = os.path.join(dirpath, f)
try:
stat = os.stat(fp)
except OSError:
continueif stat.st_ino in seen:
continue
seen.add(stat.st_ino)
total_size += stat.st_size
return total_size # size in bytes
La réponse de Chris ne prend pas non plus en compte les liens symboliques ni la taille des répertoires eux-mêmes. J'ai modifié votre réponse en conséquence, la sortie de la fonction fixe est désormais identique à df -sb.
Creshal
7
un one-liner récursif:
defgetFolderSize(p):from functools import partial
prepend = partial(os.path.join, p)
return sum([(os.path.getsize(f) if os.path.isfile(f) else getFolderSize(f)) for f in map(prepend, os.listdir(p))])
Ce n'est cependant pas une seule doublure. Cependant, il calcule de manière récursive la taille du dossier (même si le dossier contient plusieurs dossiers) en octets et donne la valeur correcte.
Venkatesh
Je suis allé pour cela aussi facile à utiliser et j'ai travaillé pour la première fois sur Windows
hum3
7
En utilisant, pathlibj'ai monté ce one-liner pour obtenir la taille d'un dossier:
sum(file.stat().st_size for file in Path(folder).rglob('*'))
Et c'est ce que j'ai proposé pour une sortie bien formatée:
Je suis également tombé sur cette question , qui a des stratégies plus compactes et probablement plus performantes pour l'impression de tailles de fichiers.
Un peu tard pour le parti , mais dans une ligne à condition que vous avez glob2 et Humaniser installé. Notez que dans Python 3, la valeur par défaut igloba un mode récursif. Comment modifier le code pour Python 3 est laissé comme un exercice trivial pour le lecteur.
>>> import os
>>> from humanize import naturalsize
>>> from glob2 import iglob
>>> naturalsize(sum(os.path.getsize(x) for x in iglob('/var/**'))))
'546.2 MB'
À partir de Python 3.5, la fonction intégrée globprend en charge la récursivité. Vous pouvez utiliser:glob.glob('/var/**', recursive=True)
adzenith
3
Le script suivant imprime la taille du répertoire de tous les sous-répertoires pour le répertoire spécifié. Il essaie également de bénéficier (si possible) de la mise en cache des appels d'une fonction récursive. Si un argument est omis, le script fonctionnera dans le répertoire courant. La sortie est triée par la taille du répertoire du plus grand au plus petit. Vous pouvez donc l'adapter à vos besoins.
Votre script fonctionne bien, mais vous devez déplacer la fonction null_decorator au-dessus de la ligne 'if sys.version_info> = ...'. Sinon, vous obtiendrez une exception «null_decorator» n'est pas définie. Fonctionne très bien après cela.
user2233949
@ user2233949, merci! J'ai modifié le code en conséquence.
J'utilise python 2.7.13 avec scandir et voici ma fonction récursive à une ligne pour obtenir la taille totale d'un dossier:
from scandir import scandir
defgetTotFldrSize(path):return sum([s.stat(follow_symlinks=False).st_size for s in scandir(path) if s.is_file(follow_symlinks=False)]) + \
+ sum([getTotFldrSize(s.path) for s in scandir(path) if s.is_dir(follow_symlinks=False)])
>>> print getTotFldrSize('.')
1203245680
Lorsque la taille des sous-répertoires est calculée, il doit mettre à jour la taille du dossier de son parent et cela continuera jusqu'à ce qu'il atteigne le parent racine.
La fonction suivante calcule la taille du dossier et de tous ses sous-dossiers.
import os
deffolder_size(path):
parent = {} # path to parent path mapper
folder_size = {} # storing the size of directories
folder = os.path.realpath(path)
for root, _, filenames in os.walk(folder):
if root == folder:
parent[root] = -1# the root folder will not have any parent
folder_size[root] = 0.0# intializing the size to 0elif root notin parent:
immediate_parent_path = os.path.dirname(root) # extract the immediate parent of the subdirectory
parent[root] = immediate_parent_path # store the parent of the subdirectory
folder_size[root] = 0.0# initialize the size to 0
total_size = 0for filename in filenames:
filepath = os.path.join(root, filename)
total_size += os.stat(filepath).st_size # computing the size of the files under the directory
folder_size[root] = total_size # store the updated size
temp_path = root # for subdirectories, we need to update the size of the parent till the root parentwhile parent[temp_path] != -1:
folder_size[parent[temp_path]] += total_size
temp_path = parent[temp_path]
return folder_size[folder]/1000000.0
import os
defget_size(path = os.getcwd()):
print("Calculating Size: ",path)
total_size = 0#if path is directory--if os.path.isdir(path):
print("Path type : Directory/Folder")
for dirpath, dirnames, filenames in os.walk(path):
for f in filenames:
fp = os.path.join(dirpath, f)
# skip if it is symbolic linkifnot os.path.islink(fp):
total_size += os.path.getsize(fp)
#if path is a file---elif os.path.isfile(path):
print("Path type : File")
total_size=os.path.getsize(path)
else:
print("Path Type : Special File (Socket, FIFO, Device File)" )
total_size=0
bytesize=total_size
print(bytesize, 'bytes')
print(bytesize/(1024), 'kilobytes')
print(bytesize/(1024*1024), 'megabytes')
print(bytesize/(1024*1024*1024), 'gegabytes')
return total_size
x=get_size("/content/examples")
Je suis sûr que cela aide! Pour les dossiers et les fichiers également!
Ce script vous indique quel fichier est le plus gros dans le CWD et vous indique également dans quel dossier se trouve le fichier. Ce script fonctionne pour moi sur win8 et python 3.3.3 shell
import os
folder=os.cwd()
number=0
string=""for root, dirs, files in os.walk(folder):
for file in files:
pathname=os.path.join(root,file)
## print (pathname)## print (os.path.getsize(pathname)/1024/1024)if number < os.path.getsize(pathname):
number = os.path.getsize(pathname)
string=pathname
## print ()print (string)
print ()
print (number)
print ("Number in bytes")
Je suis un peu en retard (et nouveau) ici mais j'ai choisi d'utiliser le module de sous-processus et la ligne de commande 'du' avec Linux pour récupérer une valeur précise de la taille du dossier en Mo. J'ai dû utiliser if et elif pour le dossier racine car sinon le sous-processus soulève une erreur en raison d'une valeur non nulle renvoyée.
import subprocess
import os
## get folder size#defget_size(self, path):if os.path.exists(path) and path != '/':
cmd = str(subprocess.check_output(['sudo', 'du', '-s', path])).\
replace('b\'', '').replace('\'', '').split('\\t')[0]
return float(cmd) / 1000000elif os.path.exists(path) and path == '/':
cmd = str(subprocess.getoutput(['sudo du -s /'])). \
replace('b\'', '').replace('\'', '').split('\n')
val = cmd[len(cmd) - 1].replace('/', '').replace(' ', '')
return float(val) / 1000000else: raise ValueError
defhumanized_size(num, suffix='B', si=False):if si:
units = ['','K','M','G','T','P','E','Z']
last_unit = 'Y'
div = 1000.0else:
units = ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']
last_unit = 'Yi'
div = 1024.0for unit in units:
if abs(num) < div:
return"%3.1f%s%s" % (num, unit, suffix)
num /= div
return"%.1f%s%s" % (num, last_unit, suffix)
Python 3.6+ taille du dossier / fichier récursif en utilisant os.scandir. Aussi puissant que dans la réponse de @blakev, mais plus court et dans le style python EAFP .
import os
defsize(path, *, follow_symlinks=False):try:
with os.scandir(path) as it:
return sum(size(entry, follow_symlinks=follow_symlinks) for entry in it)
except NotADirectoryError:
return os.stat(path, follow_symlinks=follow_symlinks).st_size
tree
commande sur les systèmes * nix fait tout cela gratuitement.tree -h -d --du /path/to/dir
.du -sh /path/to/dir/*
Réponses:
Cela parcourt tous les sous-répertoires; sommation des tailles de fichier:
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 s'amuser 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 Pour utiliser os.path.getsize , c'est plus clair que d'utiliser la méthode os.stat (). St_size.
Merci à ghostdog74 pour 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 la
walk
méthode la plus efficace fournie par lescandir
package tiers . Dans Python 3.5 et versions ultérieures, ce package a été incorporé dans la bibliothèque standard etos.walk
a reçu l'augmentation correspondante des performances.Mise à jour 2019
Récemment, j'utilise de
pathlib
plus en plus, voici unepathlib
solution:from pathlib import Path root_directory = Path('.') sum(f.stat().st_size for f in root_directory.glob('**/*') if f.is_file())
la source
st_size
si vous ne voulez pas suivre les liens symboliques, comme vous devriez alors utiliserlstat
.Certaines des approches suggérées jusqu'à présent implémentent une récursivité, d'autres utilisent un shell ou ne produiront pas de résultats parfaitement formatés. Lorsque votre code est unique pour les plates-formes Linux, vous pouvez obtenir le formatage comme d'habitude, récursivité incluse, en une seule ligne. À l'exception de la
print
dernière ligne, il fonctionnera pour les versions actuelles depython2
etpython3
: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 fonctionnera pour les fichiers et les répertoires à plusieurs niveaux:
$ chmod 750 du.py $ ./du.py 2,9M
la source
Voici une fonction récursive (elle résume récursivement la taille de tous les sous-dossiers et de leurs fichiers respectifs) qui renvoie exactement les mêmes octets que lors de l'exécution de "du -sb". sous linux (où le "." signifie "le dossier actuel"):
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("."))
la source
Taille du dossier récursif Python 3.5 en utilisant
os.scandir
def folder_size(path='.'): total = 0 for entry in os.scandir(path): if entry.is_file(): total += entry.stat().st_size elif entry.is_dir(): total += folder_size(entry.path) return total
la source
sum([entry.stat().st_size for entry in os.scandir(file)])
. La sortie de note est en octets, / 1024 pour obtenir Ko et / (1024 * 1024) pour obtenir Mo.sum(entry.stat().st_size for entry in os.scandir(file))
. Aucune raison de faire une liste, carsum
prend également des itérateurs.La réponse 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
la source
lstat
.La réponse acceptée ne prend pas en compte les liens physiques ou logiciels et compterait ces fichiers deux fois. Vous voudrez garder une 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()
la source
os.lstat
(plutôt queos.stat
), ce qui évite les liens symboliques suivants: docs.python.org/2/library/os.html#os.lstatLa réponse de Chris est bonne mais pourrait être rendue plus idiomatique en utilisant un ensemble pour vérifier les répertoires vus, ce qui évite également d'utiliser une exception pour le flux de contrôle:
def directory_size(path): total_size = 0 seen = set() for dirpath, dirnames, filenames in os.walk(path): for f in filenames: fp = os.path.join(dirpath, f) try: stat = os.stat(fp) except OSError: continue if stat.st_ino in seen: continue seen.add(stat.st_ino) total_size += stat.st_size return total_size # size in bytes
la source
df -sb
.un one-liner récursif:
def getFolderSize(p): from functools import partial prepend = partial(os.path.join, p) return sum([(os.path.getsize(f) if os.path.isfile(f) else getFolderSize(f)) for f in map(prepend, os.listdir(p))])
la source
En utilisant,
pathlib
j'ai monté ce one-liner pour obtenir la taille d'un dossier:sum(file.stat().st_size for file in Path(folder).rglob('*'))
Et c'est ce que j'ai proposé pour une sortie bien formatée:
from pathlib import Path def get_folder_size(folder): return ByteSize(sum(file.stat().st_size for file in Path(folder).rglob('*'))) class ByteSize(int): _kB = 1024 _suffixes = 'B', 'kB', 'MB', 'GB', 'PB' def __new__(cls, *args, **kwargs): return super().__new__(cls, *args, **kwargs) def __init__(self, *args, **kwargs): self.bytes = self.B = int(self) self.kilobytes = self.kB = self / self._kB**1 self.megabytes = self.MB = self / self._kB**2 self.gigabytes = self.GB = self / self._kB**3 self.petabytes = self.PB = self / self._kB**4 *suffixes, last = self._suffixes suffix = next(( suffix for suffix in suffixes if 1 < getattr(self, suffix) < self._kB ), last) self.readable = suffix, getattr(self, suffix) super().__init__() def __str__(self): return self.__format__('.2f') def __repr__(self): return '{}({})'.format(self.__class__.__name__, super().__repr__()) def __format__(self, format_spec): suffix, val = self.readable return '{val:{fmt}} {suf}'.format(val=val, fmt=format_spec, suf=suffix) def __sub__(self, other): return self.__class__(super().__sub__(other)) def __add__(self, other): return self.__class__(super().__add__(other)) def __mul__(self, other): return self.__class__(super().__mul__(other)) def __rsub__(self, other): return self.__class__(super().__sub__(other)) def __radd__(self, other): return self.__class__(super().__add__(other)) def __rmul__(self, other): return self.__class__(super().__rmul__(other))
Usage:
>>> size = get_folder_size("c:/users/tdavis/downloads") >>> print(size) 5.81 GB >>> size.GB 5.810891855508089 >>> size.gigabytes 5.810891855508089 >>> size.PB 0.005674699077644618 >>> size.MB 5950.353260040283 >>> size ByteSize(6239397620)
Je suis également tombé sur cette question , qui a des stratégies plus compactes et probablement plus performantes pour l'impression de tailles de fichiers.
la source
Pour la deuxième partie de la question
def human(size): B = "B" KB = "KB" MB = "MB" GB = "GB" TB = "TB" UNITS = [B, KB, MB, GB, TB] HUMANFMT = "%f %s" HUMANRADIX = 1024. for u in UNITS[:-1]: if size < HUMANRADIX : return HUMANFMT % (size, u) size /= HUMANRADIX return HUMANFMT % (size, UNITS[-1])
la source
Vous pouvez faire quelque chose comme ceci:
import commands size = commands.getoutput('du -sh /path/').split()[0]
dans ce cas, je n'ai pas testé le résultat avant de le renvoyer, si vous le souhaitez, vous pouvez le vérifier avec commandes.getstatusoutput.
la source
os.walk
pour vérifier la taille du sous-dossier de manière récursive?One-liner vous dites ... Voici un one-liner:
sum([sum(map(lambda fname: os.path.getsize(os.path.join(directory, fname)), files)) for directory, folders, files in os.walk(path)])
Bien que je le divise probablement et qu'il n'effectue aucun contrôle.
Pour convertir en ko, voir Bibliothèque réutilisable pour obtenir une version lisible par l'homme de la taille du fichier? et travailler dans
la source
Un peu tard pour le parti , mais dans une ligne à condition que vous avez glob2 et Humaniser installé. Notez que dans Python 3, la valeur par défaut
iglob
a un mode récursif. Comment modifier le code pour Python 3 est laissé comme un exercice trivial pour le lecteur.>>> import os >>> from humanize import naturalsize >>> from glob2 import iglob >>> naturalsize(sum(os.path.getsize(x) for x in iglob('/var/**')))) '546.2 MB'
la source
glob
prend en charge la récursivité. Vous pouvez utiliser:glob.glob('/var/**', recursive=True)
Le script suivant imprime la taille du répertoire de tous les sous-répertoires pour le répertoire spécifié. Il essaie également de bénéficier (si possible) de la mise en cache des appels d'une fonction récursive. Si un argument est omis, le script fonctionnera dans le répertoire courant. La sortie est triée par la taille du répertoire du plus grand au plus petit. Vous pouvez donc l'adapter à vos besoins.
PS, j'ai utilisé la recette 578019 pour afficher la taille du répertoire dans un format convivial ( http://code.activestate.com/recipes/578019/ )
from __future__ import print_function import os import sys import operator def null_decorator(ob): return ob if sys.version_info >= (3,2,0): import functools my_cache_decorator = functools.lru_cache(maxsize=4096) else: my_cache_decorator = null_decorator start_dir = os.path.normpath(os.path.abspath(sys.argv[1])) if len(sys.argv) > 1 else '.' @my_cache_decorator def get_dir_size(start_path = '.'): total_size = 0 if 'scandir' in dir(os): # using fast 'os.scandir' method (new in version 3.5) for entry in os.scandir(start_path): if entry.is_dir(follow_symlinks = False): total_size += get_dir_size(entry.path) elif entry.is_file(follow_symlinks = False): total_size += entry.stat().st_size else: # using slow, but compatible 'os.listdir' method for entry in os.listdir(start_path): full_path = os.path.abspath(os.path.join(start_path, entry)) if os.path.isdir(full_path): total_size += get_dir_size(full_path) elif os.path.isfile(full_path): total_size += os.path.getsize(full_path) return total_size def get_dir_size_walk(start_path = '.'): total_size = 0 for dirpath, dirnames, filenames in os.walk(start_path): for f in filenames: fp = os.path.join(dirpath, f) total_size += os.path.getsize(fp) return total_size def bytes2human(n, format='%(value).0f%(symbol)s', symbols='customary'): """ (c) http://code.activestate.com/recipes/578019/ Convert n bytes into a human readable string based on format. symbols can be either "customary", "customary_ext", "iec" or "iec_ext", see: http://goo.gl/kTQMs >>> bytes2human(0) '0.0 B' >>> bytes2human(0.9) '0.0 B' >>> bytes2human(1) '1.0 B' >>> bytes2human(1.9) '1.0 B' >>> bytes2human(1024) '1.0 K' >>> bytes2human(1048576) '1.0 M' >>> bytes2human(1099511627776127398123789121) '909.5 Y' >>> bytes2human(9856, symbols="customary") '9.6 K' >>> bytes2human(9856, symbols="customary_ext") '9.6 kilo' >>> bytes2human(9856, symbols="iec") '9.6 Ki' >>> bytes2human(9856, symbols="iec_ext") '9.6 kibi' >>> bytes2human(10000, "%(value).1f %(symbol)s/sec") '9.8 K/sec' >>> # precision can be adjusted by playing with %f operator >>> bytes2human(10000, format="%(value).5f %(symbol)s") '9.76562 K' """ SYMBOLS = { 'customary' : ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'), 'customary_ext' : ('byte', 'kilo', 'mega', 'giga', 'tera', 'peta', 'exa', 'zetta', 'iotta'), 'iec' : ('Bi', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi', 'Yi'), 'iec_ext' : ('byte', 'kibi', 'mebi', 'gibi', 'tebi', 'pebi', 'exbi', 'zebi', 'yobi'), } n = int(n) if n < 0: raise ValueError("n < 0") symbols = SYMBOLS[symbols] prefix = {} for i, s in enumerate(symbols[1:]): prefix[s] = 1 << (i+1)*10 for symbol in reversed(symbols[1:]): if n >= prefix[symbol]: value = float(n) / prefix[symbol] return format % locals() return format % dict(symbol=symbols[0], value=n) ############################################################ ### ### main () ### ############################################################ if __name__ == '__main__': dir_tree = {} ### version, that uses 'slow' [os.walk method] #get_size = get_dir_size_walk ### this recursive version can benefit from caching the function calls (functools.lru_cache) get_size = get_dir_size for root, dirs, files in os.walk(start_dir): for d in dirs: dir_path = os.path.join(root, d) if os.path.isdir(dir_path): dir_tree[dir_path] = get_size(dir_path) for d, size in sorted(dir_tree.items(), key=operator.itemgetter(1), reverse=True): print('%s\t%s' %(bytes2human(size, format='%(value).2f%(symbol)s'), d)) print('-' * 80) if sys.version_info >= (3,2,0): print(get_dir_size.cache_info())
Exemple de sortie:
37.61M .\subdir_b 2.18M .\subdir_a 2.17M .\subdir_a\subdir_a_2 4.41K .\subdir_a\subdir_a_1 ---------------------------------------------------------- CacheInfo(hits=2, misses=4, maxsize=4096, currsize=4)
EDIT: déplacé null_decorator ci-dessus, comme user2233949 recommandé
la source
use library sh : le module le
du
fait:pip install sh import sh print( sh.du("-s", ".") ) 91154728 .
si vous voulez passer astérix, utilisez
glob
comme décrit ici .pour convertir les valeurs en lisibles par l'homme, utilisez humanize :
pip install humanize import humanize print( humanize.naturalsize( 91157384 ) ) 91.2 MB
la source
pour obtenir la taille d'un fichier, il y a os.path.getsize ()
>>> import os >>> os.path.getsize("/path/file") 35L
son rapporté en octets.
la source
Pour ce que ça vaut ... la commande tree fait tout cela gratuitement:
tree -h --du /path/to/dir # files and dirs tree -h -d --du /path/to/dir # dirs only
J'adore Python, mais de loin la solution la plus simple au problème ne nécessite aucun nouveau code.
la source
C'est pratique:
import os import stat size = 0 path_ = "" def calculate(path=os.environ["SYSTEMROOT"]): global size, path_ size = 0 path_ = path for x, y, z in os.walk(path): for i in z: size += os.path.getsize(x + os.sep + i) def cevir(x): global path_ print(path_, x, "Byte") print(path_, x/1024, "Kilobyte") print(path_, x/1048576, "Megabyte") print(path_, x/1073741824, "Gigabyte") calculate("C:\Users\Jundullah\Desktop") cevir(size) Output: C:\Users\Jundullah\Desktop 87874712211 Byte C:\Users\Jundullah\Desktop 85815148.64355469 Kilobyte C:\Users\Jundullah\Desktop 83803.85609722137 Megabyte C:\Users\Jundullah\Desktop 81.83970321994275 Gigabyte
la source
J'utilise python 2.7.13 avec scandir et voici ma fonction récursive à une ligne pour obtenir la taille totale d'un dossier:
from scandir import scandir def getTotFldrSize(path): return sum([s.stat(follow_symlinks=False).st_size for s in scandir(path) if s.is_file(follow_symlinks=False)]) + \ + sum([getTotFldrSize(s.path) for s in scandir(path) if s.is_dir(follow_symlinks=False)]) >>> print getTotFldrSize('.') 1203245680
https://pypi.python.org/pypi/scandir
la source
Lorsque la taille des sous-répertoires est calculée, il doit mettre à jour la taille du dossier de son parent et cela continuera jusqu'à ce qu'il atteigne le parent racine.
La fonction suivante calcule la taille du dossier et de tous ses sous-dossiers.
import os def folder_size(path): parent = {} # path to parent path mapper folder_size = {} # storing the size of directories folder = os.path.realpath(path) for root, _, filenames in os.walk(folder): if root == folder: parent[root] = -1 # the root folder will not have any parent folder_size[root] = 0.0 # intializing the size to 0 elif root not in parent: immediate_parent_path = os.path.dirname(root) # extract the immediate parent of the subdirectory parent[root] = immediate_parent_path # store the parent of the subdirectory folder_size[root] = 0.0 # initialize the size to 0 total_size = 0 for filename in filenames: filepath = os.path.join(root, filename) total_size += os.stat(filepath).st_size # computing the size of the files under the directory folder_size[root] = total_size # store the updated size temp_path = root # for subdirectories, we need to update the size of the parent till the root parent while parent[temp_path] != -1: folder_size[parent[temp_path]] += total_size temp_path = parent[temp_path] return folder_size[folder]/1000000.0
la source
Si vous êtes sous Windows, vous pouvez faire:
installez le module pywin32 en lançant:
pip installer pywin32
puis coder ce qui suit:
import win32com.client as com def get_folder_size(path): try: fso = com.Dispatch("Scripting.FileSystemObject") folder = fso.GetFolder(path) size = str(round(folder.Size / 1048576)) print("Size: " + size + " MB") except Exception as e: print("Error --> " + str(e))
la source
Voici une ligne unique qui le fait de manière récursive (option récursive disponible à partir de Python 3.5):
import os import glob print(sum(os.path.getsize(f) for f in glob.glob('**', recursive=True) if os.path.isfile(f))/(1024*1024))
la source
pour python3.5 +
from pathlib import Path def get_size(path): return sum(p.stat().st_size for p in Path(path).rglob('*'))
la source
import os def get_size(path = os.getcwd()): print("Calculating Size: ",path) total_size = 0 #if path is directory-- if os.path.isdir(path): print("Path type : Directory/Folder") for dirpath, dirnames, filenames in os.walk(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) #if path is a file--- elif os.path.isfile(path): print("Path type : File") total_size=os.path.getsize(path) else: print("Path Type : Special File (Socket, FIFO, Device File)" ) total_size=0 bytesize=total_size print(bytesize, 'bytes') print(bytesize/(1024), 'kilobytes') print(bytesize/(1024*1024), 'megabytes') print(bytesize/(1024*1024*1024), 'gegabytes') return total_size x=get_size("/content/examples")
Je suis sûr que cela aide! Pour les dossiers et les fichiers également!
la source
Ce script vous indique quel fichier est le plus gros dans le CWD et vous indique également dans quel dossier se trouve le fichier. Ce script fonctionne pour moi sur win8 et python 3.3.3 shell
import os folder=os.cwd() number=0 string="" for root, dirs, files in os.walk(folder): for file in files: pathname=os.path.join(root,file) ## print (pathname) ## print (os.path.getsize(pathname)/1024/1024) if number < os.path.getsize(pathname): number = os.path.getsize(pathname) string=pathname ## print () print (string) print () print (number) print ("Number in bytes")
la source
Certes, c'est une sorte de piratage et ne fonctionne que sous Unix / Linux.
Cela correspond
du -sb .
car en fait, il s'agit d'un wrapper Python bash qui exécute ladu -sb .
commande.import subprocess def system_command(cmd): """"Function executes cmd parameter as a bash command.""" p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) stdout, stderr = p.communicate() return stdout, stderr size = int(system_command('du -sb . ')[0].split()[0])
la source
Je suis un peu en retard (et nouveau) ici mais j'ai choisi d'utiliser le module de sous-processus et la ligne de commande 'du' avec Linux pour récupérer une valeur précise de la taille du dossier en Mo. J'ai dû utiliser if et elif pour le dossier racine car sinon le sous-processus soulève une erreur en raison d'une valeur non nulle renvoyée.
import subprocess import os # # get folder size # def get_size(self, path): if os.path.exists(path) and path != '/': cmd = str(subprocess.check_output(['sudo', 'du', '-s', path])).\ replace('b\'', '').replace('\'', '').split('\\t')[0] return float(cmd) / 1000000 elif os.path.exists(path) and path == '/': cmd = str(subprocess.getoutput(['sudo du -s /'])). \ replace('b\'', '').replace('\'', '').split('\n') val = cmd[len(cmd) - 1].replace('/', '').replace(' ', '') return float(val) / 1000000 else: raise ValueError
la source
Obtenir la taille du répertoire
Propriétés de la solution:
du
nest.st_blocks
pour l'espace disque utilisé, ne fonctionne donc que sur les systèmes de type UnixLe code:
import os def du(path): if os.path.islink(path): return (os.lstat(path).st_size, 0) if os.path.isfile(path): st = os.lstat(path) return (st.st_size, st.st_blocks * 512) apparent_total_bytes = 0 total_bytes = 0 have = [] for dirpath, dirnames, filenames in os.walk(path): apparent_total_bytes += os.lstat(dirpath).st_size total_bytes += os.lstat(dirpath).st_blocks * 512 for f in filenames: fp = os.path.join(dirpath, f) if os.path.islink(fp): apparent_total_bytes += os.lstat(fp).st_size continue st = os.lstat(fp) if st.st_ino in have: continue # skip hardlinks which were already counted have.append(st.st_ino) apparent_total_bytes += st.st_size total_bytes += st.st_blocks * 512 for d in dirnames: dp = os.path.join(dirpath, d) if os.path.islink(dp): apparent_total_bytes += os.lstat(dp).st_size return (apparent_total_bytes, total_bytes)
Exemple d'utilisation:
>>> du('/lib') (236425839, 244363264) $ du -sb /lib 236425839 /lib $ du -sB1 /lib 244363264 /lib
Taille de fichier lisible par l'homme
Propriétés de la solution:
Le code:
def humanized_size(num, suffix='B', si=False): if si: units = ['','K','M','G','T','P','E','Z'] last_unit = 'Y' div = 1000.0 else: units = ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi'] last_unit = 'Yi' div = 1024.0 for unit in units: if abs(num) < div: return "%3.1f%s%s" % (num, unit, suffix) num /= div return "%.1f%s%s" % (num, last_unit, suffix)
Exemple d'utilisation:
>>> humanized_size(236425839) '225.5MiB' >>> humanized_size(236425839, si=True) '236.4MB' >>> humanized_size(236425839, si=True, suffix='') '236.4M'
la source
Une solution qui fonctionne sur Python 3.6 en utilisant pathlib.
from pathlib import Path sum([f.stat().st_size for f in Path("path").glob("**/*")])
la source
Python 3.6+ taille du dossier / fichier récursif en utilisant
os.scandir
. Aussi puissant que dans la réponse de @blakev, mais plus court et dans le style python EAFP .import os def size(path, *, follow_symlinks=False): try: with os.scandir(path) as it: return sum(size(entry, follow_symlinks=follow_symlinks) for entry in it) except NotADirectoryError: return os.stat(path, follow_symlinks=follow_symlinks).st_size
la source