note.nkmk.me

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

Date: 2018-02-04 / tags: Python, ファイル操作

Pythonの標準ライブラリosを使うと、ファイルのサイズ(容量)やディレクトリに含まれているファイルのサイズの合計を取得できる。

以下の3つの方法について説明する。取得できるサイズの単位はすべてバイト。

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

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

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

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

import os

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

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

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

この関数は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_symlinksFalseとする。

また、サブディレクトリを辿る必要がなければ以下の部分を削除すればOK。

            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()を使う。

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

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()の場合と同様、サブディレクトリを辿る必要がなければ以下の部分を削除すればOK。

        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
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事