Pythonでファイル、ディレクトリ(フォルダ)のサイズを取得

Pythonの標準ライブラリosを使うと、ファイルのサイズ(容量)やディレクトリに含まれているファイルのサイズの合計を取得できます。 以下の3つの方法について説明します。取得できるサイズの単位はすべてバイト。

os.path.getsize()でファイルのサイズ取得 os.scandir()を組み合わせてディレクトリのサイズ取得(Python3.5以降) os.listdir()を組み合わせてディレクトリのサイズ取得(Python3.4以前)

サイズではなくタイムスタンプ(作成日時や更新日時)を取得したい場合は

ファイルのサイズ取得: os.path.getsize()

ファイルのサイズ(容量)はos.path.getsize()で取得できます。

11.2. os.path.getsize() Python 3.6.3 ドキュメント

引数にサイズを取得したいファイルのパスを与える。

import os

print(os.path.getsize('data/src/lena_square.png'))
# 473831

ディレクトリ(フォルダ)のサイズ取得: os.scandir()を利用

ディレクトリ(フォルダ)に含まれているファイルのサイズの合計を算出するには、os.scandir()を使います。

16.1. os.scandir() — Python 3.6.3 ドキュメント

この関数はPython3.5で追加されたものなので、それ以前のバージョンではos.listdir()を使う(後述)。 以下のような関数を定義します。

def get_dir_size(path='.'):
    total = 0
    with os.scandir(path) as it:
        for entry in it:
            if entry.is_file():
                total += entry.stat().st_size
            elif entry.is_dir():
                total += get_dir_size(entry.path)
    return total

print(get_dir_size('data/src'))
# 56130856

os.scandir()で得られるos.DirEntryオブジェクトに対して、is_file(), is_dir()メソッドでファイルかディレクトリかを判定。ファイルの場合はstat_resultオブジェクトのst_size属性でサイズを取得、ディレクトリの場合はこの関数を再帰的に呼び出し、すべてのサイズを加算し合計サイズを返しています。 なお、デフォルトでは、is_file()はファイルへのシンボリックリンク、is_dir()はディレクトリへのシンボリックリンクに対してもTrueを返します。シンボリックリンクを無視したい場合は、is_file(), is_dir()の引数follow_symlinksをFalseとします。 また、サブディレクトリを辿る必要がなければ以下の部分を削除すれば問題ありません。 elif entry.is_dir(): total += get_dir_size(entry.path)

上の関数は引数にファイルのパスを渡すとエラーになります。ファイルでもディレクトリでもそのサイズを返す関数が必要な場合は以下のように書けます。

def get_size(path='.'):
    if os.path.isfile(path):
        return os.path.getsize(path)
    elif os.path.isdir(path):
        return get_dir_size(path)

print(get_size('data/src'))
# 56130856

print(get_size('data/src/lena_square.png'))
# 473831

ディレクトリ(フォルダ)のサイズ取得: os.listdir()を利用

Python3.4以前にはos.scandir()が無いので、os.listdir()を使います。

16.1. os.listdir() — Python 3.6.3 ドキュメント

以下のような関数を定義します。

def get_dir_size_old(path='.'):
    total = 0
    for p in os.listdir(path):
        full_path = os.path.join(path, p)
        if os.path.isfile(full_path):
            total += os.path.getsize(full_path)
        elif os.path.isdir(full_path):
            total += get_dir_size_old(full_path)
    return total

print(get_dir_size_old('data/src'))
# 56130856

基本的な考え方はos.scandir()の場合と同じ。 os.listdir()で取得できるのはファイル名(ディレクトリ名)なので、親ディレクトリのパスとos.path.join()で結合してフルパスを作成しています。 対象がシンボリックリンクの場合、os.path.isfile()とos.path.isdir()はその実体に対して判定するので、シンボリックリンクを無視したいときは、シンボリックリンクに対してTrueを返すos.path.islink()と組み合わせて条件判定をします。 os.scandir()の場合と同様、サブディレクトリを辿る必要がなければ以下の部分を削除すれば問題ありません。

        elif os.path.isdir(full_path):
            total += get_dir_size_old(full_path)

上の関数は引数にファイルのパスを渡すとエラーになります。ファイルでもディレクトリでもそのサイズを返す関数が必要な場合は以下のように書けます。

def get_size_old(path='.'):
    if os.path.isfile(path):
        return os.path.getsize(path)
    elif os.path.isdir(path):
        return get_dir_size_old(path)

print(get_size_old('data/src'))
# 56130856

print(get_size_old('data/src/lena_square.png'))
# 473831
Last Updated: 6/26/2019, 10:34:03 PM