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


当前回答

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

其他回答

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

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

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

你可以这样做:

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

在这种情况下,我没有在返回之前测试结果,如果你想要,你可以用commands.getstatusoutput检查它。

蒙纳特的答案是很好的,但它失败的符号链接,所以你还必须检查这个路径是否真的存在

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

不可否认,这有点像黑客,只适用于Unix/Linux。

它匹配du -sb。因为实际上这是一个Python bash包装器,它运行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])

使用库sh: du模块执行:

pip install sh

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

如果您想传递asterix,请使用此处描述的glob。

要转换human readable中的值,请使用humanize:

pip install humanize

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