使用Python计算目录大小?
在我重新发明这个轮子之前,有没有人能分享一个用Python计算文件夹大小的好方法?如果这个方法能把大小格式化得好看一点,比如用Mb或Gb来显示,那就更好了。
34 个回答
33
我用 pathlib
写了一个一行代码,可以用来获取文件夹的大小:
sum(file.stat().st_size for file in Path(folder).rglob('*'))
这是我为输出结果格式化而写的代码:
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))
使用方法:
>>> 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)
我还看到这个 问题,里面有一些更简洁、可能更高效的打印文件大小的方法。
70
到目前为止,有些方法使用了递归,有些则用了一些外部工具,结果可能也不太整齐。如果你的代码只是为了在Linux平台上用一次,那么你可以像往常一样得到格式化的结果,包括递归,这一切都可以用一行代码实现。除了最后一行的print
,这段代码在当前版本的python2
和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('.'))
这段代码简单高效,适用于文件和多层目录:
$ chmod 750 du.py
$ ./du.py
2,9M
401
这段代码会遍历所有子目录,并计算文件的大小:
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')
还有一个有趣的单行代码,使用了 os.listdir (不包括子目录):
import os
sum(os.path.getsize(f) for f in os.listdir('.') if os.path.isfile(f))
参考资料:
- os.path.getsize - 返回文件大小(以字节为单位)
- os.walk
- os.path.islink
更新
使用 os.path.getsize 这个方法比用 os.stat().st_size 方法更清晰。
感谢 ghostdog74 提醒这一点!
os.stat - st_size 返回文件大小(以字节为单位)。也可以用来获取文件大小和其他与文件相关的信息。
import os
nbytes = sum(d.stat().st_size for d in os.scandir('.') if d.is_file())
2018年更新
如果你使用的是 Python 3.4 或更早版本,可以考虑使用第三方的 scandir
包提供的更高效的 walk
方法。在 Python 3.5 及以后的版本中,这个包已经被整合进标准库,os.walk
的性能也得到了相应的提升。
2019年更新
最近我越来越多地使用 pathlib
,这里有一个 pathlib
的解决方案:
from pathlib import Path
root_directory = Path('.')
sum(f.stat().st_size for f in root_directory.glob('**/*') if f.is_file())