【问题标题】:Directory sizes and extensions目录大小和扩展名
【发布时间】:2011-08-21 12:51:49
【问题描述】:

我想创建 python 命令行代码,该代码能够打印具有所有子目录大小(来自某个目录)和最常见扩展名的目录树...我将展示示例输出。

  • root_dir (5 GB, jpg (65 %): avi (30 %) : pdf (5 %))

-- aa (3 GB, jpg (100 %) )

-- bb (2 GB, avi (20 %) : pdf (2 %) )

--- bbb (1 GB, ...)

--- bb2 (1 GB, ...)

-- cc (1 GB, pdf (100 %) )

格式为:

嵌套级别,目录名称(包含所有文件和子目录的目录大小,该目录中最常见的扩展以及大小百分比。

到目前为止,我有this 代码 sn-p。问题是它只计算目录中的文件大小,因此结果大小小于目录的实际大小。另一个问题是如何将它们放在一起打印我上面定义的树而不进行冗余计算。

【问题讨论】:

  • 到目前为止,您是否编写过任何代码或规划过任何逻辑?请发帖。

标签: python directory file-extension


【解决方案1】:

计算目录大小确实不是 python 的强项,正如本文所述:very quickly getting total size of folder。如果您可以访问dufind,请务必使用它。您可以使用以下行轻松显示每个目录的大小:

find . -type d -exec du -hs "{}" \;

如果您坚持在 python 中执行此操作,您可能更喜欢 post-order traversal 而不是 os.walk,正如 PableG 所建议的那样。但是使用os.walk 可以在视觉上更干净,如果效率不是你的最重要因素:

import os, sys
from collections import defaultdict

def walkIt(folder):
    for (path, dirs, files) in os.walk(folder):
        size = getDirSize(path)
        stats = getExtensionStats(files)

        # only get the top 3 extensions
        print '%s (%s, %s)'%(path, size, stats[:3])

def getExtensionStats(files):
    # get all file extensions
    extensions = [f.rsplit(os.extsep, 1)[-1] 
        for f in files if len(f.rsplit(os.extsep, 1)) > 1]

    # count the extensions
    exCounter = defaultdict(int)
    for e in extensions:
        exCounter[e] += 1

    # convert count to percentage
    percentPairs = [(e, 100*ct/len(extensions)) for e, ct in exCounter.items()]

    # sort them
    percentPairs.sort(key=lambda i: i[1])
    return percentPairs

def getDirSize(root):
    size = 0
    for path, dirs, files in os.walk(root):
        for f in files:
            size +=  os.path.getsize( os.path.join( path, f ) )
    return size

if __name__ == '__main__':
    path = sys.argv[1] if len(sys.argv) > 1 else '.'
    walkIt(path)

【讨论】:

    【解决方案2】:

    我个人认为 os.listdir + a_recursive_function 比 os.walk 更适合这个任务:

    import os, copy
    from os.path import join, getsize, isdir, splitext
    
    frequent_ext = { ".jpg": 0, ".pdf": 0 }     # Frequent extensions
    
    def list_dir(base_dir):
        dir_sz = 0  # directory size
        files = os.listdir(base_dir)
        ext_size = copy.copy(frequent_ext)
    
        for file_ in files:
            file_ = join(base_dir, file_)
    
            if isdir(file_):
                ret = list_dir(file_)
                dir_sz += ret[0]
                for k, v in frequent_ext.items():           # Add to freq.ext.sizes
                    ext_size[k] += ret[1][k]
            else:
                file_sz = getsize(file_)
                dir_sz += file_sz
    
                ext = os.path.splitext(file_)[1].lower()   # Frequent extension?
                if ext in frequent_ext.keys():
                    ext_size[ext] += file_sz
    
        print base_dir, dir_sz,
        for k, v in ext_size.items():
            print "%s: %5.2f%%" % (k, float(v) / max(1, dir_sz) * 100.),
    
        print 
    
        return (dir_sz, ext_size)
    
    
    base_dir = "e:/test_dir/"
    base_dir = os.path.abspath(base_dir)
    list_dir(base_dir)
    

    【讨论】:

    • 谢谢,你的代码教会了我Python的好东西,我尝试使用os.walk,但是使用起来相当复杂。你的递归看起来很优雅。我正在尝试测试它,但它给了我error
    • 我注意到它崩溃的目录是符号链接。如果可能的话,可以避免符号链接。我现在在 Linux (Ubuntu) 上测试它,但主要用途是在 Windows 7 上。
    【解决方案3】:

    @Cldy 使用 os.path 是对的

    例如os.path.walk 将首先遍历参数下面的每个目录,并返回每个目录中的文件和文件夹

    使用os.path.getsize 获取大小并拆分以获取扩展名。将扩展存储在列表或字典中,并在遍历每个

    后对它们进行计数

    如果您使用的是 Linux,我建议您改为查看 du

    【讨论】:

      【解决方案4】:

      这就是你need 的模块。还有this

      【讨论】:

      • 那些将是最有用的模块。 +1。也许可以输入一个 dict 来跟踪扩展和大小。
      • 如果您只想将某人指向一个模块,而不是说其他​​任何内容,请使用评论。如果你要回答,至少给他们指出具体的功能,或者让他们知道如何解决这个问题。 (我不是反对者,我当天没有票,但我同意)。
      • 我指出这些模块是因为我认为它们已经足够好并且文档是不言自明的。也许你是对的,这更适合作为评论。但是文档说明了一切,所以我不会改变我的答案。
      猜你喜欢
      • 1970-01-01
      • 2015-04-07
      • 1970-01-01
      • 1970-01-01
      • 2021-03-09
      • 1970-01-01
      • 2013-09-29
      • 2020-05-16
      • 1970-01-01
      相关资源
      最近更新 更多