Pythonでディレクトリのサイズを一覧表示する

Twitterでシェア FaceBookでシェア はてなブックマークでシェア

Python - 標準ライブラリ
2018年11月22日21:25に更新(約21日前)
2018年11月12日0:21に作成(約32日前)

概要

Pythonで、ディレクトリのサイズを一覧表示するプログラムを作成していきます。

Python、pathlibモジュールを使うでも紹介した、pathlibモジュールを利用して作成します。

見た目

python main.py
.idea 8.1 KiB
main.py 1.8 KiB

ソースコード

from pathlib import Path

SUFFIXES = {
    1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
    1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
}


def approximate_size(size, a_kilobyte_is_1024_bytes=True):
    """Convert a file size to human-readable form.

    http://diveintopython3-ja.rdy.jp/your-first-python-program.html

    Keyword arguments:
    size -- file size in bytes
    a_kilobyte_is_1024_bytes -- if True (default), use multiples of 1024
                                if False, use multiples of 1000

    Returns: string

    """
    if size < 0:
        raise ValueError('number must be non-negative')

    multiple = 1024 if a_kilobyte_is_1024_bytes else 1000
    for suffix in SUFFIXES[multiple]:
        size /= multiple
        if size < multiple:
            return '{0:.1f} {1}'.format(size, suffix)

    raise ValueError('number too large')


def _get_size(path_obj):
    """そのパスのサイズを返す。

    Pathオブジェクトを受け取ります。

    ファイルだった場合はそのファイルサイズを、
    ディレクトリだった場合は再帰的に取得したファイルサイズを返します。

    """
    if path_obj.is_file():
        return path_obj.stat().st_size
    elif path_obj.is_dir():
        return sum(_get_size(p) for p in path_obj.iterdir())


def get_size(target_path='.'):
    """Pathオブジェクトとサイズをyieldで返す。

    サイズを取得したいパスを与えると、中にあるパスの一覧とそれぞれのサイズを
    yieldで返します。

    """
    for path in Path(target_path).iterdir():
        size = _get_size(path)
        yield path, approximate_size(size)


if __name__ == '__main__':
    for name, size in get_size():
        print(name, size)

以下はDive Into PythonというPythonの入門サイト(のWeb版)にあった、ファイルサイズの変換処理です。 8277のような数値を与えると、8.1 KiBのような文字列に変換してくれます。

SUFFIXES = {
    1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
    1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
}


def approximate_size(size, a_kilobyte_is_1024_bytes=True):
    """Convert a file size to human-readable form.

    http://diveintopython3-ja.rdy.jp/your-first-python-program.html

    Keyword arguments:
    size -- file size in bytes
    a_kilobyte_is_1024_bytes -- if True (default), use multiples of 1024
                                if False, use multiples of 1000

    Returns: string

    """
    if size < 0:
        raise ValueError('number must be non-negative')

    multiple = 1024 if a_kilobyte_is_1024_bytes else 1000
    for suffix in SUFFIXES[multiple]:
        size /= multiple
        if size < multiple:
            return '{0:.1f} {1}'.format(size, suffix)

    raise ValueError('number too large')

docstringの通りで、中にあるファイル・ディレクトリ一覧をiterdir()で取得し、ファイルサイズを実際に取得する処理である_get_size()に渡します。サイズを取得し終わったら、Pathオブジェクトと一緒に返却します。

def get_size(target_path='.'):
    """Pathオブジェクトとサイズをyieldで返す。

    サイズを取得したいパスを与えると、中にあるパスの一覧とそれぞれのサイズを
    yieldで返します。

    """
    for path in Path(target_path).iterdir():
        size = _get_size(path)
        yield path, approximate_size(size)


if __name__ == '__main__':
    for name, size in get_size():
        print(name, size)

こちらが本命のファイルサイズ取得処理です。.stat().st_sizeでファイルのサイズが取得できます。ディレクトリだった場合は中にあるファイルを合算する必要がありますので、iterdir()を呼び出し各パスをまた_get_sizeに渡します。

def _get_size(path_obj):
    """そのパスのサイズを返す。

    Pathオブジェクトを受け取ります。

    ファイルだった場合はそのファイルサイズを、
    ディレクトリだった場合は再帰的に取得したファイルサイズを返します。

    """
    if path_obj.is_file():
        return path_obj.stat().st_size
    elif path_obj.is_dir():
        return sum(_get_size(p) for p in path_obj.iterdir())
Twitterでシェア FaceBookでシェア はてなブックマークでシェア

記事にコメントする