【Python】フォルダ操作で便利なサンプル紹介

Pythonで効率的にフォルダ操作を行いたいけれど、どのモジュールを使えば良いか迷うことは無いですか?

本記事では、os、shutil、glob、pathlibという4つの標準ライブラリを駆使して、フォルダの作成や削除、名前変更、コピー、移動、存在確認など、さまざまな操作を行うサンプルコードを紹介します。

これらの関数はそのままコピペして使えるので、実際のプロジェクトでも役立つものとなっています。

Pythonでのフォルダ操作を行いたい方は、是非本記事をご一読ください。

目次

フォルダ操作に使える標準ライブラリ内の4つのモジュール

Pythonの標準ライブラリには、フォルダ操作を行うためのモジュールとして、 osshutilglobpathlib が存在します。これらは、それぞれ以下の違いがあります。

ライブラリ特徴
osWindowsやLinuxなどのオペレーティングシステムに対して基本的な操作を行うためのライブラリです。指定したファイルやフォルダの作成、削除、名前変更、移動などの操作が可能です。
shutil指定したフォルダに対して、その配下にあるフォルダやファイルを丸ごとコピー、移動、削除することができます。
glob指定したフォルダに対して、その配下にあるファイル名を全て取得する関数です。フォルダを操作する機能はありません。
pathlibファイルシステムのパスをオブジェクト指向で操作できるライブラリです。ファイルやフォルダのパスを簡単に作成、変更、比較、操作することができます。

ケース別フォルダ操作

フォルダの作成と削除

フォルダを作成する方法として、os.makedirs()pathlib.Path.mkdir()の2つがあります。
どちらも親フォルダも含めて一度に複数のフォルダを作成することができます(但し mkdir は parents=Trueの指定が必要)。
すでにフォルダが存在している場合、どちらもexist_ok=Trueを指定することでエラーを防げます。

import os

# 親フォルダを含めて作成。既に存在する場合は何もしない
os.makedirs('C:/example_folder/sub_folder', exist_ok=True)
from pathlib import Path

# 親フォルダを含めて作成。既に存在する場合は何もしない
Path('C:/example_folder/sub_folder').mkdir(parents=True, exist_ok=True)

フォルダを削除する場合はshutil.rmtree() を使います。shutil.rmtree()はフォルダ配下にあるファイルとフォルダを丸ごと削除してくれます。
os.rmdir() はフォルダが空の場合のみ利用可能です(ファイルが存在するとエラーになります)。

import shutil

# フォルダを丸ごと削除
shutil.rmtree('C:/example_folder/sub_folder')
import os

# フォルダが空の場合のみ削除可能(空でない場合はエラーとなる)
os.rmdir('C:/example_folder/sub_folder')

フォルダの名前変更と移動

フォルダの名前変更には、osライブラリやpathlibライブラリに用意されている rename()が使えます。

import os

# フォルダ名の名前を変更
os.rename('C:/example_folder/old_folder', 'C:/example_folder/new_folder')
from pathlib import Path

# フォルダ名の名前を変更
Path('C:/example_folder/old_folder').rename('C:/example_folder/new_folder')

フォルダ移動を行う場合、shutilライブラリの move() を使います。

import shutil

# 別フォルダにフォルダを丸ごと移動
shutil.move('C:/example_folder/new_folder', 'D:/another_folder/new_folder')

同一フォルダ内の移動(階層の位置を変える)だけであれば、rename()も利用できます。

# 同一フォルダ内の移動をos.renameで行う場合
os.rename('C:/example_folder/old_folder', 'C:/example_folder/sub_folder/subsub_folder/new_folder')

# 同一フォルダ内の移動をPath.renameで行う場合
Path('C:/example_folder/old_folder').rename('C:/example_folder/sub_folder/subsub_folder/new_folder')

フォルダのコピー

フォルダのコピーには、shutilライブラリのcopytree()を使用します。指定したフォルダを丸ごとコピーしてくれるだけでなく、コピー先フォルダが存在しない場合は、自動で作成もしてくれます。

import shutil

# フォルダを丸ごとコピー
shutil.copytree('C:/example_folder', 'D:/backup_folder')

フォルダ情報の取得

フォルダの作成日や最終更新日などのメタデータは、osライブラリや pathlibに用意されているstat()を使います。

import os
import time

# osのstat()を使ってフォルダのプロパティを取得
stat_info = os.stat('C:/example_folder')

# 最終更新日時
last_modified = time.ctime(stat_info.st_mtime)

# 作成日時(Windowsの場合)
creation_time = time.ctime(stat_info.st_ctime)

print(f"最終更新日時:{last_modified} 作成日時:{creation_time}")
from pathlib import Path
import time

# pathlibのstat()を使ってフォルダのプロパティを取得
stat_info = Path('C:/example_folder').stat()

# 最終更新日時
last_modified = time.ctime(stat_info.st_mtime)

# 作成日時(Windowsの場合)
creation_time = time.ctime(stat_info.st_ctime)

最終更新日時、作成日、アクセス日時は 1970年1月1日 00:00:00 UTC からの経過秒になるため、変換が必要です。

# yyyy/mm/dd hh:mm:ss フォーマットの文字列に変換して表示
last_modified = datetime.datetime.strptime(last_modified, "%a %b %d %H:%M:%S %Y")
creation_datetime = datetime.datetime.strptime(creation_time, "%a %b %d %H:%M:%S %Y") 

print(f"最終更新日時:{last_modified.strftime('%Y/%m/%d %H:%M:%S')}")
print(f"作成日時:{creation_datetime.strftime('%Y/%m/%d %H:%M:%S')}")

最終更新日時:2024/11/04 19:21:05
作成日時:2024/07/27 19:53:34

フォルダ情報にはタイムスタインプ以外にも、多くの情報が取得できます。より詳しい内容は「【Python】ファイルパス/フォルダパスの分解と結合で便利なサンプル紹介(os、pathlib)」の記事にまとめています。

あわせて読みたい
【Python】ファイルパス/フォルダパスの分解と結合で便利なサンプル紹介(os、pathlib) Pythonでフォルダやファイルのパス操作を行う際に便利なライブラリとして、従来のosモジュールと、新しいpathlibモジュールがあります。 それぞれに特徴があり、同じタ...

フォルダの存在確認とパスの分解・結合

フォルダの存在確認は、 os ライブラリに用意されているisdir()pathliライブラリに用意されている is_dir() が利用できます。
両ライブラリとも同様の機能を持つメソッドとしてexists() も用意されていますが、こちらはフォルダ/ファイルのどちらであっても、存在すればTrue返します。

機能ospathlib説明
フォルダの存在確認os.path.isdir()path.is_dir()フォルダが有ればTrue、無ければFalseが返る
パスの存在確認os.path.exists()path.exists()フォルダ/ファイルの区別なく有ればTrue
import os

# osライブラリを使ったフォルダの存在確認
if os.path.isdir('C:/example_folder'):
    print(f"フォルダ '{path}' は存在します。")
else:
    print(f"フォルダ '{path}' は存在しません。")

# osライブラリを使ったフォルダ/ファイルの存在確認
if os.path.exists('C:/example_folder'):
    print(f"フォルダまたはファイル '{path}' は存在します。")
else:
    print(f"フォルダまたはファイル'{path}' は存在しません。")
from pathlib import Path

# pathlibライブラリを使ったフォルダの存在確認
if Path(C:/example_folder').is_dir():
    print(f"フォルダ '{path}' は存在します。")
else:
    print(f"フォルダ '{path}' は存在しません。")

# pathlibライブラリを使ったフォルダ/ファイルの存在確認
if if Path(C:/example_folder').exists():
    print(f"フォルダまたはファイル '{path}' は存在します。")
else:
    print(f"フォルダまたはファイル'{path}' は存在しません。")

フォルダ内のファイルやサブフォルダの一覧取得

glob はファイル名を取得する関数であるため、本記事では割愛します。詳しく知りたい方は、「【Python】ファイル名の取得で便利なサンプル紹介(ワイルドカード対応)」をご一読ください。

あわせて読みたい
【Python】ファイル名の取得で便利なサンプル紹介(ワイルドカード対応) 自作プログラムを作成する中で、ファイル名の一覧を取得したい場合がよくあります。 フォルダ内のファイルやサブフォルダを効率的に扱うためには、いくつかの方法があり...

便利な関数サンプル集

差分コピー

このプログラムは、バックアップ元とバックアップ先のフォルダを比較し、異なるファイルやフォルダをコピーするものです。バックアップ対象がフォルダの場合はshutil.copytree を、ファイルの場合はshutil.copy2を使ってコピーしています。

バックアップ元とバックアップ先の比較には filecmp.cmp を使っています。引数に shallow=False を渡すと、メタ情報(ファイルスタンプ、サイズなど)を使って比較してくれます。もしファイルの中身を比較したい場合、shallow=True に変更してください。

import os
import shutil
import glob
import filecmp

def folder_backup(source_folder: str, backup_folder: str):
    """
    フォルダの差分バックアップを行う関数。
    
    :param source_folder: バックアップ元のフォルダ
    :param backup_folder: バックアップ先のフォルダ
    """
    # バックアップフォルダが存在しない場合は作成
    if not os.path.exists(backup_folder):
        os.makedirs(backup_folder)

    # ソースフォルダ内のアイテム(ファイルやサブフォルダ)をチェック
    items = glob.glob(os.path.join(source_folder, '*'))

    for item_path in items:
        item = os.path.basename(item_path)
        backup_item_path = os.path.join(backup_folder, item)

        # バックアップ先に同じアイテムがない、または内容が異なる場合にコピー
        if not os.path.exists(backup_item_path) or not filecmp.cmp(item_path, backup_item_path, shallow=False):
            if os.path.isdir(item_path):
                shutil.copytree(item_path, backup_item_path, dirs_exist_ok=True)
            else:
                shutil.copy2(item_path, backup_item_path)
            print(f'差分バックアップしました: {item}')
# 使用例
source_folder = 'p:/csv'
backup_folder = 'x:/backup/csv_backup'

folder_backup(source_folder, backup_folder)

拡張子別にフォルダを分類する

このプログラムは、指定されたフォルダ内のファイルを拡張子に分類するものです。extensions に拡張子を記述することで、分類対象の拡張子が指定できます。また、 is_move = True を指定することで、ファイルの移動が可能です。

import os
import shutil
import glob

def classify_files_by_extension(source_folder: str, destination_folder: str, extensions: list, is_move: bool=False):
    """
    ファイルを拡張子ごとにフォルダに分類する関数。
    
    :param source_folder: 元のフォルダのパス
    :param destination_folder: 分類されたファイルを保存するフォルダのパス
    :param extensions: 分類する拡張子のリスト
    :param is_move: True ならファイルを移動、False ならファイルをコピー
    """
    # ファイルを取得(再帰的)
    files = glob.glob(os.path.join(source_folder, '**', '*.*'), recursive=True)

    for file_path in files:
        if os.path.isfile(file_path) and file_path.split('.')[-1].lower() in extensions:
            extension = file_path.split('.')[-1].lower()
            target_folder = os.path.join(destination_folder, extension)
            os.makedirs(target_folder, exist_ok=True)
            target_path = os.path.join(target_folder, os.path.basename(file_path))
            
            if is_move:
                shutil.move(file_path, target_path)
                print(f'{os.path.basename(file_path)} を {extension} フォルダに移動しました。')
            else:
                shutil.copy2(file_path, target_path)
                print(f'{os.path.basename(file_path)} を {extension} フォルダにコピーしました。')
# 使用例
source_folder = 'p:/data'
destination_folder_extension = 'x:/backup/extension'
extensions = ['txt', 'csv', 'png']  # 分類する拡張子を指定

# 拡張子ごとに分類(コピー)
classify_files_by_extension(source_folder, destination_folder_extension, extensions, move=False)

作成日別にフォルダを分類する

このプログラムは、指定されたフォルダ内のファイルを作成日別に分類するものです。前述の classify_files_by_extension と同じく、extensions に拡張子を記述することで、分類対象の拡張子が指定できます。
また、 is_move = True を指定することで、ファイルの移動が可能です。

import os
import shutil
import glob
import datetime

def classify_files_by_creation_date(source_folder: str, destination_folder: str, extensions: list, move: bool=False):
    """
    ファイルを作成日ごとにフォルダに分類する関数。
    
    :param source_folder: 元のフォルダのパス
    :param destination_folder: 分類されたファイルを保存するフォルダのパス
    :param extensions: 分類する拡張子のリスト
    :param move: True ならファイルを移動、False ならファイルをコピー
    """
    # ファイルを取得(再帰的)
    files = glob.glob(os.path.join(source_folder, '**', '*.*'), recursive=True)

    for file_path in files:
        if os.path.isfile(file_path) and file_path.split('.')[-1].lower() in extensions:
            creation_time = datetime.datetime.fromtimestamp(os.path.getctime(file_path))
            date_folder = creation_time.strftime('%Y-%m-%d')
            target_folder = os.path.join(destination_folder, date_folder)
            os.makedirs(target_folder, exist_ok=True)
            target_path = os.path.join(target_folder, os.path.basename(file_path))
            
            if move:
                shutil.move(file_path, target_path)
                print(f'{os.path.basename(file_path)} を {date_folder} フォルダに移動しました。')
            else:
                shutil.copy2(file_path, target_path)
                print(f'{os.path.basename(file_path)} を {date_folder} フォルダにコピーしました。')
# 使用例
source_folder = 'p:/csv'
destination_folder_date = 'x:/backup/date'
extensions = ['txt', 'csv', 'png']  # 分類する拡張子を指定

# 作成日ごとに分類(コピー)
classify_files_by_creation_date(source_folder, destination_folder_date, extensions, move=False)

まとめ

この記事では、Pythonでフォルダ操作を行うための標準ライブラリであるos、shutil、glob、pathlibの使い方を紹介しました。

各モジュールの特徴を理解し、ケース別に適切な操作を行うことで、フォルダの作成、削除、名前変更、コピー、移動、存在確認など、多岐にわたるタスクを効率的に実行できます。

また、具体的なサンプルコードを提供することで、すぐに実践に移せるようにしました。

本記事の内容が、あなたのPythonプログラミングに役立てば幸いです。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

目次