Calculer la taille d'un répertoire en utilisant Python?
24 réponses
ceci saisit les sous-répertoires:
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)
total_size += os.path.getsize(fp)
return total_size
print get_size()
et un oneliner pour s'amuser avec 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:
os.chemin.getsize - donne la taille en octets
mise à Jour Utiliser os.chemin.getsize , c'est plus clair que d'utiliser l'os.stat().méthode st_size.
merci à ghostdog74 de le souligner!
os.stat - st_size donne la taille en octets. Peut également être utilisé pour obtenir la taille du fichier et d'autres informations liées au fichier.
mise à Jour 2018
si vous utilisez Python 3.4 ou avant, vous pouvez envisager d'utiliser la méthode plus efficace walk
fournie par le tiers scandir
package. En Python 3.5 et plus tard, ce paquet a été incorporé dans la bibliothèque standard et os.walk
a reçu l'augmentation correspondante de performance.
certaines des approches suggérées jusqu'à présent mettent en œuvre une récursion, d'autres emploient un shell ou ne produiront pas de résultats parfaitement formatés. Quand votre code est unique pour les plates-formes Linux, vous pouvez obtenir le formatage comme d'habitude, recursion incluse, comme une doublure unique. Sauf pour le print
dans la dernière ligne, il fonctionnera pour les versions actuelles de python2
et 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 fonctionnera pour les fichiers et les répertoires à plusieurs niveaux:
$ chmod 750 du.py
$ ./du.py
2,9M
un peu en retard après 5 ans, mais parce que c'est toujours dans les listes d'hitlérisme des moteurs de recherche, il pourrait être utile...
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 ."dans linux (où l' "."signifie le "dossier en cours"):
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("."))
Python 3.5 Taille du dossier récursif 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 réponse de monknut est bonne mais elle échoue sur le lien symbolique cassé, donc vous devez aussi vérifier si ce chemin existe vraiment
if os.path.exists(fp):
total_size += os.stat(fp).st_size
la réponse acceptée ne prend pas en compte les liens durs ou mous, et compterait ces fichiers deux fois. Vous voudriez garder la trace des inodes que vous avez vu, et ne pas ajouter la taille pour ces dossiers.
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 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
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])
vous pouvez faire quelque chose comme ça:
import commands
size = commands.getoutput('du -sh /path/').split()[0]
dans ce cas, je n'ai pas testé le résultat avant de le retourner, si vous le souhaitez, vous pouvez vérifier avec les commandes.getstatusoutput.
une doublure, dites-vous... Voici une doublure:
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 l'aurais probablement divisé et il n'effectue pas de vérifications.
pour convertir en kb voir bibliothèque réutilisable pour obtenir une version lisible par l'homme de la taille du fichier? et le travailler en
un peu en retard à la partie mais en une ligne à condition que vous ayez 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'
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 profiter (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 des plus grands aux plus petits. De sorte que vous pouvez 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())
sortie de L'échantillon:
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)
modifier: null_décorator déplacé ci-dessus, comme user2233949 recommandé
utilisation de la bibliothèque sh : le module du
:
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 humaniser :
pip install humanize
import humanize
print( humanize.naturalsize( 91157384 ) )
91.2 MB
pour obtenir la taille d'un fichier, il y a os.chemin.getsize ()
>>> import os
>>> os.path.getsize("/path/file")
35L
sa en octets.
si vous êtes dans Windows OS vous pouvez faire:
installer le module pywin32 en lançant:
pip install pywin32
et codant ensuite 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))
Il est à portée de main:
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
ce script vous indique quel fichier est le plus grand dans le CWD et vous indique également dans quel dossier le fichier est. 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")
certes, il s'agit d'une sorte de hackish et ne fonctionne que sur Unix/Linux.
correspond à du -sb .
car il s'agit en fait d'un enveloppeur Python bash qui exécute la commande du -sb .
.
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])
j'utilise python 2.7.13 avec scandir et voici ma fonction de recursive à une doublure 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
quand la taille des sous-répertoires est calculée, il doit mettre à jour la taille du dossier de son parent et cela va continuer jusqu'à ce qu'il atteigne le parent racine.
La fonction suivante calcule la taille du dossier et 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
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'aime Python, mais de loin la solution la plus simple au problème ne nécessite pas de nouveau code.
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 pour la taille du dossier en MB. J'ai dû utiliser IF et elif pour le dossier racine parce que sinon subprocess soulève l'erreur due à la valeur non-nulle retourné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
import os
def get_size(path):
total_size = 0
for dirpath, dirnames, filenames in os.walk(path):
for f in filenames:
if os.path.exists(fp):
fp = os.path.join(dirpath, f)
total_size += os.path.getsize(fp)
return total_size # in megabytes
Merci monkut & troex! Cela fonctionne vraiment bien!