[python]フォルダ容量を設定して超える場合は古いファイルから削除するプログラム

python
スポンサーリンク

フォルダ容量を設定して超える場合は古いファイルから削除するプログラム

はじめに

私がいつも使用している「動画を自動的に記録するアプリ」があるのですが、ある更新から古いファイルが削除されず、膨大に膨れ上がるようになってしまいました。
気づくとSSDがいっぱに。。。

なぜそのような仕様にしたかはわかりませんが、私には不都合があるため、自動的に古いファイルは削除するプログラムをPythonで作成しました。

開発環境

OS : Windows 11 Pro
Python:3.13.2
使用ライブラリ:なし

プログラム

仕様

①フォルダ容量が設定が超えている場合は作成日時の古いファイルから削除すること。
②削除対象ファイルの拡張子指定ができるようにすること。
③PC使用者に意識させないためバックグラウンドで実行すること。
④できればPC使用時には負荷がかからないようアイドル時に実行すること。

④に関しては、Windowsのタスクスケジューラに登録することで実現するとして、①~③をPythonスクリプトで動作するようにします。

注意事項

仕様にもあるように、バックグラウンドで実行することを目的としています。
そのため、ファイル削除する際に確認プロンプトなど表示せず、瞬時に削除します。誤って使用すると大事なファイルが削除されることがあるため、使用方法をよくご覧になってご使用ください。

Pythonスクリプト

GitHub:https://github.com/farmsoft-jp/RemvByFolderSize
ダウンロードはこちら☝️

# ---------------------------------------------------------------------------
# フォルダ容量を設定して超える場合は古いファイルから削除するプログラム
# https://www.farmsoft.jp/2461/
# ---------------------------------------------------------------------------
import os       # OSに依存しているさまざまな機能を利用するためのモジュール
import glob     # 引数に指定されたパターンにマッチするファイルパス名を取得
import math     # C標準で定義された数学関数へのアクセスを取得
# ---------------------------------------------------------------------------
# 設定
# ---------------------------------------------------------------------------
G_SIZE = 25     # 最大フォルダサイズ(G byte)
TYPES  = '*'    # 削除対象とするファイル拡張子を指定
                # ex) TYPES = 'mp4', 'png'  ⇒ *.mp4 *.png のみ削除対象とする
                # ex) TYPES = '*'           ⇒ 指定なし
# ---------------------------------------------------------------------------
SIZE   = G_SIZE*1024*1024*1024
# ---------------------------------------------------------------------------
# フォルダサイズを算出する関数
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
# ---------------------------------------------------------------------------
# バイトを適切な単位に変換する関数
def convert_size(size):
    units = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB")
    i = math.floor(math.log(size, 1024)) if size > 0 else 0
    size = round(size / 1024 ** i, 2)
    return f"{size} {units[i]}"
# ---------------------------------------------------------------------------
def remv():
    path = os.path.dirname(__file__) + '\\'     # 本実行スクリプトの絶対パスを取得
    script_path = __file__                      # 本実行スクリプトの絶対パス+ファイル名を取得
    folder_size = get_dir_size(path)            # フォルダサイズ算出

    # フォルダサイズが最大フォルダサイズより小さい場合は終了
    if folder_size <= SIZE:
        print(f'現在のフォルダサイズは[{convert_size(folder_size)}]です。')
        return
    # 削除するサイズを計算
    rsize = folder_size - SIZE

    # フォルダ内にある対象拡張子のファイル一覧を取得
    files = []
    for t in TYPES:
        files += glob.glob(path + '*' + t)
    if len(files) == 0:
        print(f'現在のフォルダサイズは[{convert_size(folder_size)}]です。')
        return

    # ファイル名と作成日時(エポック秒)の2次元リストを作成
    # [['ファイル名', 作成日時(エポック秒)],['ファイル名', 作成日時(エポック秒)],...]
    flist = []
    for file in files:
        # 本実行スクリプトは除外
        if file == script_path:
            continue
        # ファイルリストに['ファイル名', 作成日時(エポック秒)]を追加
        f_name = os.path.basename(file)
        ctime  = os.path.getctime(file)
        flist.append([f_name, ctime])

    # ファイルリストを要素2つ目の作成日時(エポック秒)で昇順ソート
    flist.sort(key=lambda x: x[1])

    # ファイルリストの作成日時(エポック秒)が古いものからファイルサイズを取得し、
    # 削除するファイルを特定
    total = 0
    lv = []
    i = 0
    for i in range(len(flist)):
        # フォルダは除外しファイルのみ対象
        if os.path.isfile(path + flist[i][0]):
            total += os.path.getsize(path + flist[i][0])
            lv.append(i)
            if rsize <= total:
                break
    print(f'{i+1}個のファイル(合計サイズ[{convert_size(total)}])を削除します。')

    # 特定したファイルを削除
    for i in range(len(lv)):
        os.remove(path + flist[lv[i]][0])
        print(f'削除したファイル名:{flist[lv[i]][0]}')
    print(f'現在のフォルダサイズは[{convert_size(folder_size-total)}]です。')
# ---------------------------------------------------------------------------
if __name__=='__main__':
    remv()
# ---------------------------------------------------------------------------

設定説明

フォルダ容量設定
G_SIZE = 25     # 最大フォルダサイズ(G byte)

フォルダ容量を11行目「G_SIZE = 25」で設定します。単位は G byte です。
ここで設定した容量を超える場合は、古いファイルから削除します。
また、サブフォルダ内の容量もカウントします。

SIZE   = G_SIZE*1024*1024*1024

単位を変更する場合は、SIZE を調整してください。
(M byte に変更する場合は「SIZE = G_SIZE*1024*1024」など」)

ファイル拡張子設定
TYPES  = '*'    # 削除対象とするファイル拡張子を指定
                # ex) TYPES = 'mp4', 'png'  ⇒ *.mp4 *.png のみ削除対象とする
                # ex) TYPES = '*'           ⇒ 指定なし

削除対象のファイル拡張子を「TYPES = ‘*’」で設定します。
フォルダ容量を超えてファイルを削除する際のファイル拡張を指定できます。
ここで指定していないファイル拡張子は削除されません。
また、サブフォルダ内はいずれの拡張子も削除対象にしていません。

コード説明

コメントにて説明を記載していますので、一部のみ記載します。

ファイル日時

今回は、作成日時を使用していますが、別の日時を使用する場合は os.path.getctime(path) を変更します。

        ctime  = os.path.getctime(file)
  • os.path.getatime(path): 最終アクセス日時
  • os.path.getmtime(path): 最終内容更新日時
  • os.path.getctime(path): メタデータの最終更新日時(Unix系など一部のシステム) / 作成日時(Windows などその他のシステム)

公式ドキュメント – 3.13.2

使用方法

監視対象とするフォルダ内に「RemvByFolderSize.py」のみ配置して実行してください。
ターミナルウィンドウを表示させないようにするにはこちら👇

Windowsタスクスケジュラに登録しておけば、定期的に監視して削除してくれます。

おわりに

似たようなアプリが公開されていなかったため、作成しました。

コメント

タイトルとURLをコピーしました