Hat jemand vor der Neuerfindung dieses speziellen Rads eine schöne Routine zur Berechnung der Größe eines Verzeichnisses mit Python? Es wäre sehr schön, wenn die Routine die Größe schön in Mb/Gb usw. formatieren würde.
Dadurch werden Unterverzeichnisse erfasst:
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()
Und ein Online-Spass mit os.listdir (Enthält keine Unterverzeichnisse):
import os
sum(os.path.getsize(f) for f in os.listdir('.') if os.path.isfile(f))
Referenz:
os.path.getsize - Gibt die Größe in Byte an
Updated Die Verwendung von os.path.getsize ist klarer als bei Verwendung der Methode os.stat (). St_size.
Danke an ghostdog74 für den Hinweis!
os.stat - st_size Gibt die Größe in Byte an. Kann auch zum Abrufen der Dateigröße und anderer dateibezogener Informationen verwendet werden.
Update 2018
Wenn Sie Python 3.4 oder eine frühere Version verwenden, sollten Sie die effizientere walk
-Methode in Erwägung ziehen, die vom Drittanbieterpaket scandir
bereitgestellt wird. In Python 3.5 und höher wurde dieses Paket in die Standardbibliothek aufgenommen, und os.walk
erhielt die entsprechende Leistungssteigerung.
Einige der bisher vorgeschlagenen Ansätze implementieren eine Rekursion, andere verwenden eine Shell oder liefern keine sauber formatierten Ergebnisse. Wenn Ihr Code für Linux-Plattformen einmalig ist, können Sie die Formatierung wie gewohnt (Rekursion eingeschlossen) als Einzeiler erhalten. Mit Ausnahme der print
in der letzten Zeile funktioniert es für aktuelle Versionen von python2
und 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 __== "__main__":
print(du('.'))
ist einfach, effizient und funktioniert für Dateien und mehrstufige Verzeichnisse:
$ chmod 750 du.py
$ ./du.py
2,9M
Nach 5 Jahren etwas spät, aber da dies immer noch in den Hitlisten der Suchmaschinen steht, könnte es hilfreich sein ...
Hier ist eine rekursive Funktion (sie summiert rekursiv die Größe aller Unterordner und ihrer jeweiligen Dateien), die genau die gleichen Bytes zurückgibt wie beim Ausführen von "du -sb" in Linux (wobei "." für "den aktuellen Ordner" steht):
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("."))
Rekursive Ordnergröße von Python 3.5 mit 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
die Antwort von monknut ist gut, schlägt jedoch bei einem fehlerhaften Symlink fehl. Sie müssen auch prüfen, ob dieser Pfad wirklich vorhanden ist
if os.path.exists(fp):
total_size += os.stat(fp).st_size
Die akzeptierte Antwort berücksichtigt keine Hard- oder Softlinks und würde diese Dateien zweimal zählen. Sie möchten nachverfolgen, welche Inodes Sie gesehen haben, und nicht die Größe für diese Dateien hinzufügen.
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()
Chris 'Antwort ist gut, könnte aber idiomatischer gemacht werden, indem ein Satz verwendet wird, um nach erkannten Verzeichnissen zu suchen. Dadurch wird auch die Verwendung einer Ausnahme für den Steuerungsfluss vermieden:
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
ein rekursiver Einzeiler:
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))])
Für den zweiten Teil der Frage
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])
Sie können so etwas tun:
import commands
size = commands.getoutput('du -sh /path/').split()[0]
in diesem Fall habe ich das Ergebnis vor der Rückgabe nicht getestet. Wenn Sie möchten, können Sie es mit Befehlen.getstatusoutput überprüfen.
Etwas spät zur Party, aber in einer Zeile, sofern Sie glob2 und humanize installiert haben. Beachten Sie, dass die Standardvariable iglob
in Python 3 einen rekursiven Modus hat. Wie der Code für Python 3 geändert werden kann, ist für den Leser eine einfache Übung.
>>> import os
>>> from humanize import naturalsize
>>> from glob2 import iglob
>>> naturalsize(sum(os.path.getsize(x) for x in iglob('/var/**'))))
'546.2 MB'
Einliner sagen Sie ....__ Hier ist ein Einliner:
sum([sum(map(lambda fname: os.path.getsize(os.path.join(directory, fname)), files)) for directory, folders, files in os.walk(path)])
Ich würde es wahrscheinlich aufteilen und es führt keine Prüfungen durch.
Um nach kb zu konvertieren, siehe Wiederverwendbare Bibliothek, um eine lesbare Version der Dateigröße zu erhalten. und arbeite es ein
Es ist praktisch:
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
Das folgende Skript gibt die Verzeichnisgröße aller Unterverzeichnisse für das angegebene Verzeichnis aus. Es versucht auch (wenn möglich) vom Zwischenspeichern der Aufrufe einer rekursiven Funktion zu profitieren. Wenn ein Argument ausgelassen wird, funktioniert das Skript im aktuellen Verzeichnis. Die Ausgabe wird nach der Verzeichnisgröße vom größten bis zum kleinsten sortiert. So können Sie es an Ihre Bedürfnisse anpassen.
PS Ich habe Rezept 578019 verwendet, um die Verzeichnisgröße in einem benutzerfreundlichen Format anzuzeigen ( 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 __== '__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())
Beispielausgabe:
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)
BEARBEITEN: Null_decorator wurde nach oben verschoben, wie von Benutzer2233949 empfohlen
benutze die Bibliothek sh : das Modul du
macht es:
pip install sh
import sh
print( sh.du("-s", ".") )
91154728 .
wenn Sie ein Sternchen übergeben möchten, verwenden Sie glob
wie beschrieben hier .
um die Werte in lesbare Werte umzuwandeln, verwenden Sie humanize :
pip install humanize
import humanize
print( humanize.naturalsize( 91157384 ) )
91.2 MB
um die Größe einer Datei zu ermitteln, gibt es os.path.getsize ().
>>> import os
>>> os.path.getsize("/path/file")
35L
sein in Bytes angegeben.
Wenn die Größe der Unterverzeichnisse berechnet wird, sollte die Ordnergröße des übergeordneten Elements aktualisiert werden. Dies wird so lange fortgesetzt, bis der übergeordnete Stamm erreicht wird.
Die folgende Funktion berechnet die Größe des Ordners und aller seiner Unterordner.
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
Ich benutze Python 2.7.13 mit scandir und hier ist meine rekursive Einzeilerfunktion, um die Gesamtgröße eines Ordners zu ermitteln:
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
Wenn Sie Windows verwenden, können Sie Folgendes tun:
installieren Sie das Modul pywin32, indem Sie Folgendes starten:
pip install pywin32
und dann folgendes kodieren:
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))
Hier ist ein Einzeiler, der dies rekursiv durchführt (rekursive Option ab Python 3.5 verfügbar):
import os
import glob
print(sum(os.path.getsize(f) for f in glob.glob('**', recursive=True) if os.path.isfile(f))/(1024*1024))
Eine Lösung, die unter Python 3.6 mit pathlib funktioniert.
from pathlib import Path
sum([f.stat().st_size for f in Path("path").glob("**/*")])
Mit pathlib
bin ich auf diesen Einzeiler gekommen, um die Größe eines Ordners zu erhalten:
sum(file.stat().st_size for file in Path(folder).rglob('*'))
Und das habe ich mir für eine schön formatierte Ausgabe ausgedacht:
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))
Verwendungszweck:
>>> 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)
Ich bin auch auf diese frage gestoßen, die kompaktere und wahrscheinlich performantere Strategien hat.
Dieses Skript zeigt Ihnen, welche Datei die größte Datei in der CWD ist, und teilt Ihnen mit, in welchem Ordner sich die Datei befindet .. _ Dieses Skript funktioniert für mich unter Win8 und 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")
Für das, was es wert ist ... der Baumbefehl macht das alles kostenlos:
tree -h --du /path/to/dir # files and dirs
tree -h -d --du /path/to/dir # dirs only
Ich liebe Python, aber die einfachste Lösung für das Problem erfordert keinen neuen Code.
für python3.5 +
from pathlib import Path
def get_size(path):
return sum(p.stat().st_size for p in Path(path).rglob('*'))
Ich bin etwas spät (und neu) hier, aber ich entschied mich für das Subprozess-Modul und die Befehlszeile "du" unter Linux, um einen genauen Wert für die Ordnergröße in MB abzurufen. Ich musste if und Elif für den Root-Ordner verwenden, da der Unterprozess ansonsten einen Fehler aufgrund des zurückgegebenen Werts ungleich Null verursacht.
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
Zugegeben, das ist ziemlich hackig und funktioniert nur unter Unix/Linux.
Sie stimmt mit du -sb .
überein, da dies tatsächlich ein Python-Bash-Wrapper ist, der den du -sb .
-Befehl ausführt.
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])
def recursive_dir_size(path):
size = 0
for x in os.listdir(path):
if not os.path.isdir(os.path.join(path,x)):
size += os.stat(os.path.join(path,x)).st_size
else:
size += recursive_dir_size(os.path.join(path,x))
return size
Ich habe diese Funktion geschrieben, die mir die genaue Gesamtgröße eines Verzeichnisses angibt. Ich habe andere Lösungen für Schleifen mit os.walk ausprobiert, aber ich weiß nicht, warum das Endergebnis immer kleiner als die tatsächliche Größe war (auf Ubuntu 18 env). Ich muss etwas falsch gemacht haben, aber wen interessiert das?.
Python 3.6 + rekursive Ordner-/Dateigröße mit os.scandir
. So mächtig wie im answer by @blakev, aber kürzer und im EAFP python style .
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
Eigenschaften der Lösung:
du
st.st_blocks
für den verwendeten Speicherplatz, funktioniert also nur auf Unix-ähnlichen SystemenDer 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)
Beispielverwendung:
>>> du('/lib')
(236425839, 244363264)
$ du -sb /lib
236425839 /lib
$ du -sB1 /lib
244363264 /lib
Eigenschaften der Lösung:
Der 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)
Beispielverwendung:
>>> humanized_size(236425839)
'225.5MiB'
>>> humanized_size(236425839, si=True)
'236.4MB'
>>> humanized_size(236425839, si=True, suffix='')
'236.4M'