データのバックアップを作成したり、テンプレートフォルダを複製して新しいプロジェクトを開始したりする際、ファイルやディレクトリのコピー操作は欠かせません。
Pythonの標準ライブラリである shutil モジュール(Shell Utilitiesの略)を使用すると、これらの操作を簡単な関数呼び出しで実行できます。
この記事では、単一のファイルをコピーする shutil.copy() と、ディレクトリツリーごとコピーする shutil.copytree() の使い方について解説します。
1. ファイルをコピーする: shutil.copy()
shutil.copy() 関数は、指定されたファイルを別の場所にコピーします。
構文:
import shutil
shutil.copy(コピー元パス, コピー先パス)
- コピー元 (src): コピーしたいファイルのパス。
- コピー先 (dst): コピー先のファイルパス、またはディレクトリパス。
具体的な使用例
重要なプレゼンテーション資料のバックアップを作成する例です。
import shutil
import os
# コピー元のファイル
source_file = "presentation_v1.pptx"
# コピー先のディレクトリ(事前に作成しておく)
backup_dir = "backup_storage"
if not os.path.exists(backup_dir):
os.makedirs(backup_dir)
print(f"コピー元: {source_file}")
# 1. ファイル名を指定してコピー(リネームしてコピー)
# "backup_storage/presentation_v1_bk.pptx" として保存される
new_path = shutil.copy(source_file, os.path.join(backup_dir, "presentation_v1_bk.pptx"))
print(f"バックアップ作成完了: {new_path}")
# 2. ディレクトリを指定してコピー
# "backup_storage/presentation_v1.pptx" (同名) として保存される
dest_path = shutil.copy(source_file, backup_dir)
print(f"ディレクトリへのコピー完了: {dest_path}")
実行結果:
コピー元: presentation_v1.pptx
バックアップ作成完了: backup_storage/presentation_v1_bk.pptx
ディレクトリへのコピー完了: backup_storage/presentation_v1.pptx
補足: copy2() について
shutil モジュールには copy() とよく似た copy2() という関数もあります。 copy() はファイルの内容と権限(パーミッション)のみをコピーしますが、copy2() はそれに加えてメタデータ(作成日時や更新日時など)も可能な限りコピーします。完全なバックアップが必要な場合は copy2() の使用を推奨します。
2. ディレクトリを丸ごとコピーする: shutil.copytree()
ディレクトリの中に含まれるサブディレクトリやファイルを、構造を保ったまま丸ごとコピーするには shutil.copytree() を使用します。
構文:
import shutil
shutil.copytree(コピー元ディレクトリ, コピー先ディレクトリ)
重要な注意点: 原則として、コピー先のディレクトリは存在してはいけません。copytree() は実行時にコピー先ディレクトリを新規作成します。もし既に存在する場合は FileExistsError が発生します(Python 3.8以降では dirs_exist_ok=True オプションで上書き可能です)。
具体的な使用例
開発用のアセットフォルダ(画像やCSSなど)を、リリース用のフォルダとして複製する例です。
import shutil
import os
# 開発用ディレクトリ(コピー元)
dev_assets = "project/dev/assets"
# リリース用ディレクトリ(コピー先)
# このディレクトリはまだ存在していない必要がある
release_dir = "project/release/v1.0/assets"
print("アセットの複製を開始します...")
try:
# ディレクトリツリー全体をコピー
shutil.copytree(dev_assets, release_dir)
print(f"成功: '{dev_assets}' を '{release_dir}' にコピーしました。")
except FileExistsError:
print(f"エラー: コピー先 '{release_dir}' は既に存在します。")
except FileNotFoundError:
print(f"エラー: コピー元 '{dev_assets}' が見つかりません。")
実行結果:
アセットの複製を開始します...
成功: 'project/dev/assets' を 'project/release/v1.0/assets' にコピーしました。
これにより、dev/assets 内のすべてのファイルとサブフォルダが、再帰的に release/v1.0/assets 内にコピーされます。
まとめ
shutil.copy(src, dst): ファイルをコピーします。dstがディレクトリならその中に同名で保存されます。shutil.copy2(src, dst): ファイル内容に加え、タイムスタンプなどのメタデータもコピーします。shutil.copytree(src, dst): ディレクトリ全体を再帰的にコピーします。基本的にdstは新規作成されるディレクトリである必要があります。
ファイルの整理やバックアップ処理を自動化するスクリプトにおいて、shutil は非常に強力なツールとなります。
