指定フォルダ以下のフォルダ内サイズを一覧表示

空フォルダややたらとサイズが大きいファイルを格納しているフォルダを探す時に、フォルダ内の合計ファイルサイズを確認したい時がある。1フォルダであればフォルダのプロパティから確認できるが、複数を確認しようとすると面倒。Linuxならduコマンドをシェルで適当に回して確認するが、Windowsだとツールを入れないと一括では調べられない。
この目的だけであればフリーツールもたくさんあるが、あとで別プログラムで利用したかったので、Pythonで自分で書き起こしてみた。

目次

  1. ソース
  2. 補足

ソース

import os

class Dirs:
    class DirInfo:
        def __init__(self, root, dirs, files):
            self.root = root
            self.dirs = dirs
            self.files = files
            self.depth = root.count(os.path.sep)
            self.num_files = len(files)
            self.num_dirs = len(dirs)
            self.sum_size = sum(os.path.getsize(os.path.join(root, file)) for file in files)

    def __init__(self, root_path):
        self.dict_dirs = {root: Dirs.DirInfo(root, dirs, files) for root, dirs, files in os.walk(root_path)}
        for di in sorted(self.dict_dirs.values(), key=lambda di: di.depth, reverse=True):
            for child_dir in di.dirs:
                child_di = self.dict_dirs[os.path.join(di.root, child_dir)]
                di.num_files += child_di.num_files
                di.num_dirs += child_di.num_dirs
                di.sum_size += child_di.sum_size

if __name__ == '__main__':
    path = "C:\\path\\to\\folder"
    dirs = Dirs(path)
    for di in sorted(dirs.dict_dirs.values(), key=lambda di: di.root):
        print(di.depth, di.root, di.num_dirs, di.num_files, di.sum_size)

補足

Dirsクラス内にDirInfoクラスを作成している。メンバとコンストラクタを定義しているのみで、リストのIndexアクセスだと可読性が悪かったためだけ。
class Dirs:
    class DirInfo: ...


階層の深いフォルダからフォルダ内のファイルサイズ合計を積み上げていきたいので、フォルダ階層の深さ(=\の個数)を数えている。
            self.depth = root.count(os.path.sep)


フォルダに格納しているファイル数、フォルダ数もついでに数えるためメンバを定義。
            self.num_files = len(files)
            self.num_dirs = len(dirs)


os.walkで階層的にフォルダにアクセスしている。返値で得られるroot,dirs,filesを自作クラスのDirInfoに格納し、そのまま内包表記でroot(フォルダパス)をキーとする辞書を作成。
    def __init__(self, root_path):
        self.dict_dirs = {root: Dirs.DirInfo(root, dirs, files) for root, dirs, files in os.walk(root_path)}


フォルダ階層の深いフォルダから順次計算するようkey=lambda di: di.depthでソート順序を指定したうえでソートし、for文を回している。
    def __init__(self, root_path):
 ...
        for di in sorted(self.dict_dirs.values(), key=lambda di: di.depth, reverse=True):


子フォルダのファイル数、フォルダ数、サイズ合計を足しあげ。
    def __init__(self, root_path):
 ...
            for child_dir in di.dirs:
                child_di = self.dict_dirs[os.path.join(di.root, child_dir)]
                di.num_files += child_di.num_files
                di.num_dirs += child_di.num_dirs
                di.sum_size += child_di.sum_size



コメント

このブログの人気の投稿

Python SQLite スレッド間でコネクションの使いまわしは出来ない

slackでgeneralの投稿を全削除する

Google location history(JSON形式)をCSVファイルにする