ChatGPT解决这个技术问题 Extra ChatGPT

使用 Python 计算目录的大小?

在我重新发明这个特殊的轮子之前,有没有人有一个很好的例程来使用 Python 计算目录的大小?如果例程能以 Mb/Gb 等格式很好地格式化大小,那就太好了。

这不会很好。您应该有一个函数来计算大小和一个非常独立的函数(例如,它也可以与内存大小一起使用)来“以 Mb/Gb 等格式很好地格式化大小”。
是的,我知道,但这可以省去问两个问题。
*nix 系统上的 tree 命令免费完成所有这些工作。 tree -h -d --du /path/to/dir
@meh du -sh /path/to/dir/*

m
monkut

这会遍历所有子目录;汇总文件大小:

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 的 oneliner(不包括子目录):

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())


+1 但 oneliner 不返回有效结果,因为它不是递归的
是的,它只是用于平面目录的情况。
为了真正有趣,您可以在一行中执行递归大小: sum( os.path.getsize(os.path.join(dirpath,filename)) for dirpath, dirnames, filenames in os.walk( PATH ) for filenames in filenames
但是,如果您不想遵循符号链接,则必须使用 st_size,因为您应该使用 lstat
警告!这与“du -sb”不同。见塞缪尔·兰帕的答案!您的代码忽略了用于存储 FAT 的文件夹的大小。
A
Asclepius

到目前为止建议的一些方法实现了递归,其他方法使用 shell 或者不会产生格式整齐的结果。当您的代码是针对 Linux 平台的一次性代码时,您可以像往常一样获得格式化,包括递归,作为单行。除了最后一行中的 print,它将适用于当前版本的 python2python3

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

Python本质上是跨平台的,可能应该回避这个
感谢您的这些评论。我在答案中添加了一些关于平台依赖性的警告。但是,大部分 Python 代码都是一次性脚本。此类代码不应带有功能限制、冗长且容易出错的段落,或在边缘情况下不常见的结果,只是为了超出任何需要的可移植性。一如既往,这是一种权衡,开发人员有责任做出明智的选择;)
Nitpick:不是 Linux,而是 Unix/Posix 特定的 :)
将“-x”选项添加到 du 命令以将搜索限制在文件系统中可能是明智的。换句话说,请改用 ['du', '-shx', path]。
S
Samuel Lampa

这是一个递归函数(它递归地总结所有子文件夹及其各自文件的大小),它返回与运行“du -sb”时完全相同的字节。在 linux 中(“.”表示“当前文件夹”):

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("."))

这个函数也计算符号链接的大小 - 如果你想跳过符号链接,你必须检查不是这样:如果 os.path.isfile(itempath) 和 os.path.islink(itempath) 和 elif os.path.isdir( itempath) 和 os.path.islink(itempath)。
b
blakev

使用 os.scandir 的 Python 3.5 递归文件夹大小

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

如果不担心递归sum([entry.stat().st_size for entry in os.scandir(file)]),则使用 Python 3 单线方法。注意输出以字节为单位,/1024 获取 KB,/(1024*1024) 获取 MB。
@weiji14 去掉括号,即sum(entry.stat().st_size for entry in os.scandir(file))。没有理由列出一个列表,因为 sum 也采用迭代器。
这个答案在 Windows 上是迄今为止最有效的,因为 DirEntry.stat() does not require an additional system call per file
T
Terry Davis

使用 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)

我还遇到了这个 question,它有一些更紧凑且可能更高效的打印文件大小的策略。


如果存在无效的符号链接将失败: FileNotFoundError: [Errno 2] No such file or directory
if file.exists() 添加到理解中可以解决这个问题吗?我猜 Path.lstat 也可以,但我认为它会通过重复计算符号链接来扩大结果的大小。
t
troex

蒙克努特的回答很好,但在符号链接损坏时会失败,所以你还必须检查这条路径是否真的存在

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

您可能不想遵循符号链接。您应该使用 lstat
W
Waket Zheng

对于python3.5+

from pathlib import Path

def get_size(folder: str) -> int:
    return sum(p.stat().st_size for p in Path(folder).rglob('*'))

用法::

In [6]: get_size('/etc/not-exist-path')
Out[6]: 0
In [7]: get_size('.')
Out[7]: 12038689
In [8]: def filesize(size: int) -> str:
   ...:     for unit in ("B", "K", "M", "G", "T"):
   ...:         if size < 1024:
   ...:             break
   ...:         size /= 1024
   ...:     return f"{size:.1f}{unit}"
   ...:

In [9]: filesize(get_size('.'))
Out[9]: '11.5M'


谢谢我正在寻找平均文件大小计算!
C
Chris

接受的答案不考虑硬链接或软链接,并且会将这些文件计算两次。您希望跟踪您看到的 inode,而不是添加这些文件的大小。

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()

考虑使用 os.lstat(而不是 os.stat),这样可以避免以下符号链接:docs.python.org/2/library/os.html#os.lstat
佚名

递归单行:

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))])

虽然它不是一个班轮。但是,它以字节为单位递归计算文件夹大小(即使文件夹中有多个文件夹)并给出正确的值。
我这样做很容易使用,并且第一次在 Windows 上工作
a
andrewh

克里斯的回答很好,但可以通过使用集合来检查看到的目录来变得更加惯用,这也避免了对控制流使用异常:

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

克里斯的回答也没有考虑符号链接或目录本身的大小。我已相应地编辑了您的答案,固定函数的输出现在与 df -sb 相同。
该功能误报/不幸的是
S
Sardathrion - against SE abuse

聚会有点晚了,但只要您安装了 glob2humanize 就可以了。请注意,在 Python 3 中,默认的 iglob 具有递归模式。如何修改 Python 3 的代码留给读者做一个简单的练习。

>>> import os
>>> from humanize import naturalsize
>>> from glob2 import iglob
>>> naturalsize(sum(os.path.getsize(x) for x in iglob('/var/**'))))
'546.2 MB'

从 Python 3.5 开始,内置 glob 支持递归。您可以使用:glob.glob('/var/**', recursive=True)
M
Mmmh mmh

对于问题的第二部分

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])

g
ghostdog74

获取一个文件的大小,有 os.path.getsize()

>>> import os
>>> os.path.getsize("/path/file")
35L

它以字节为单位报告。


g
gypaetus

你可以这样做:

import commands   
size = commands.getoutput('du -sh /path/').split()[0]

在这种情况下,我没有在返回结果之前对其进行测试,如果您愿意,可以使用 commands.getstatusoutput 进行检查。


与使用 os.walk 递归检查子文件夹大小相比,性能如何?
C
Community

你说的单线......这是一个单线:

sum([sum(map(lambda fname: os.path.getsize(os.path.join(directory, fname)), files)) for directory, folders, files in os.walk(path)])

尽管我可能会将其拆分出来并且它不执行任何检查。

要转换为 kb,请参见 Reusable library to get human readable version of file size? 并使用它


M
MaxU - stop genocide of UA

以下脚本打印指定目录的所有子目录的目录大小。它还尝试从缓存递归函数的调用中受益(如果可能)。如果省略参数,则脚本将在当前目录中运行。输出按目录大小从大到小排序。因此,您可以根据需要对其进行调整。

PS 我使用配方 578019 以人性化的格式显示目录大小 (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())

样本输出:

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)

编辑:将 null_decorator 移到上面,正如 user2233949 推荐的那样


您的脚本运行良好,但您需要将 null_decorator 函数移到 'if sys.version_info >= ...' 行上方。否则你会得到一个“null_decorator”未定义异常。不过在那之后效果很好。
@user2233949,谢谢!我相应地修改了代码。
0
0 _

使用库 sh:模块 du 执行以下操作:

pip install sh

import sh
print( sh.du("-s", ".") )
91154728        .

如果您想通过 asterix,请使用 glob,如 here 所述。

要转换人类可读的值,请使用 humanize

pip install humanize

import humanize
print( humanize.naturalsize( 91157384 ) )
91.2 MB

C
Cloudomation

获取目录大小

溶液的性质:

返回两者:表观大小(文件中的字节数)和文件使用的实际磁盘空间。

只计算一次硬链接文件

以与 du 相同的方式计算符号链接

不使用递归

使用 st.st_blocks 作为磁盘空间,因此仅适用于类 Unix 系统

编码:

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)

示例用法:

>>> du('/lib')
(236425839, 244363264)

$ du -sb /lib
236425839   /lib
$ du -sB1 /lib
244363264   /lib

人类可读文件大小

溶液的性质:

支持高达 Yottabytes

支持 SI 单位或 IEC 单位

支持自定义后缀

编码:

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)

示例用法:

>>> humanized_size(236425839)
'225.5MiB'
>>> humanized_size(236425839, si=True)
'236.4MB'
>>> humanized_size(236425839, si=True, suffix='')
'236.4M'

total_bytes 计算正是我想要的!这里没有其他解决方案可以计算这一点。 du -sh 命令实际上给了我总字节数,而不是明显的总字节数。谢谢!
m
meh

对于它的价值...... tree 命令免费完成所有这些:

tree -h --du /path/to/dir  # files and dirs
tree -h -d --du /path/to/dir  # dirs only

我喜欢 Python,但到目前为止,最简单的问题解决方案不需要新代码。


@Abdur-RahmaanJanhangeer,这是真的。这是真实的。
佚名

它很方便:

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

d
delica

这是一个以递归方式执行的单行程序(从 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))

J
Jonathan Rolfsen
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

我编写了这个函数,它为我提供了准确的目录整体大小,我尝试了其他 for 循环解决方案,使用 os.walk,但我不知道为什么最终结果总是小于实际大小(在 ubuntu 18 env 上)。我一定做错了什么,但谁在乎写这个工作得很好。


A
Akarius

我正在使用带有 scandir 的 python 2.7.13,这是我的单行递归函数来获取文件夹的总大小:

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


N
Nirvik Ghosh

当计算子目录的大小时,它应该更新其父文件夹的大小,这将一直持续到它到达根父目录。

以下函数计算文件夹及其所有子文件夹的大小。

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

S
Striped

使用 pathlib 在 Python 3.6 上运行的解决方案。

from pathlib import Path

sum([f.stat().st_size for f in Path("path").glob("**/*")])

p
petertc

du 默认情况下不遵循符号链接。这里没有答案使用follow_symlinks=False

这是一个遵循 du 的默认行为的实现:

def du(path) -> int:
    total = 0
    for entry in os.scandir(path):
        if entry.is_file(follow_symlinks=False):
            total += entry.stat().st_size
        elif entry.is_dir(follow_symlinks=False):
            total += du(entry.path)
    return total

测试:

class Test(unittest.TestCase):
    def test_du(self):
        root = '/tmp/du_test'
        subprocess.run(['rm', '-rf', root])
        test_utils.mkdir(root)
        test_utils.create_file(root, 'A', '1M')
        test_utils.create_file(root, 'B', '1M')
        sub = '/'.join([root, 'sub'])
        test_utils.mkdir(sub)
        test_utils.create_file(sub, 'C', '1M')
        test_utils.create_file(sub, 'D', '1M')
        subprocess.run(['ln', '-s', '/tmp', '/'.join([root, 'link']), ])
        self.assertEqual(4 << 20, util.du(root))

F
Farhan Hai Khan
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")

我相信这会有所帮助!对于文件夹和文件也是如此!


u
user3762880

此脚本告诉您 CWD 中哪个文件最大,并告诉您文件在哪个文件夹中。这个脚本适用于我的 win8 和 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")

a
alfonso

诚然,这有点骇人听闻,只适用于 Unix/Linux。

它与 du -sb . 匹配,因为实际上这是一个运行 du -sb . 命令的 Python bash 包装器。

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])

T
Tomas Oliver Ramilison

我在这里有点晚了(和新的),但我选择使用子进程模块和 Linux 的“du”命令行来检索以 MB 为单位的文件夹大小的准确值。我不得不将 if 和 elif 用于根文件夹,否则子进程会由于返回非零值而引发错误。

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