Python 業務自動化 | ファイル・フォルダ自動化:基本操作 - ファイルコピー

Python Python
スポンサーリンク

Pythonで「ファイルコピー」を業務レベルで使いこなす

業務自動化でファイルコピーは、ほぼ必ずと言っていいほど登場します。
「毎日生成されるレポートをバックアップフォルダにコピーする」「特定の拡張子のファイルだけを別フォルダに集める」「処理前に元データを退避しておく」──こういう作業は、全部ファイルコピーの応用です。

Pythonでは、標準ライブラリの shutil モジュールを使うことで、シンプルかつ安全にファイルコピーを行えます。
ここから、初心者向けに「まずこれだけ押さえればOK」というところから、実務でそのまま使えるテンプレートまで、一気に整理していきます。


ファイルコピーの主役:shutil.copy と shutil.copy2

shutilモジュールとは何者か

shutil は「shell utilities」の略で、シェル(コマンドプロンプトやターミナル)でやっているようなファイル操作を、Pythonから簡単に扱えるようにした標準モジュールです
インストールは不要で、import shutil と書くだけで使えます。

ファイルコピーでよく使うのは、次の2つです。

shutil.copy(src, dst)
ファイルの中身とパーミッション(権限)をコピーする。メタデータ(作成日時など)はあまり気にしない場合向け。

shutil.copy2(src, dst)
できる限りメタデータ(作成日時・更新日時など)も含めてコピーする。より「元ファイルに近い状態でコピーしたい」場合向け。

初心者のうちは「細かいメタデータは気にしない」ことが多いので、まずは shutil.copy から慣れていくと良いです。

いちばんシンプルなコピーコード

まずは「1つのファイルを、別の場所にコピーする」最小コードを見てみましょう。

import shutil

src = "data/report.txt"          # コピー元
dst = "backup/report_backup.txt" # コピー先

shutil.copy(src, dst)
print("コピー完了")
Python

このコードは、data/report.txt の内容を backup/report_backup.txt にコピーします。
もし backup/report_backup.txt がすでに存在していれば、何の確認もなく上書きされます。ここが実務上の重要ポイントです。


重要ポイントを深掘り:src と dst の意味と挙動

dst が「ファイル名」か「フォルダ名」かで挙動が変わる

shutil.copy(src, dst) の第二引数 dst は、少しクセがあります。
dst が「既存のフォルダ」なのか、「ファイルパス」なのかで挙動が変わるからです。

次の2パターンを比べてみましょう。

import shutil

# パターン1: dst を「ファイルパス」として指定
shutil.copy("data/report.txt", "backup/report_backup.txt")

# パターン2: dst を「既存のフォルダ」として指定
shutil.copy("data/report.txt", "backup")
Python

パターン1では、「backup/report_backup.txt」というファイルが作られます。
パターン2では、「backup」フォルダの中に「report.txt」という名前でコピーされます(元ファイル名がそのまま使われるイメージです)。

ここで特に気をつけたいのは、「dst に存在しないフォルダパスを指定しても、そのフォルダは自動では作られない」という点です。
つまり、"backup/2024" というフォルダが存在しない状態でそこを指定すると、エラーになります。

コピー前に「フォルダがあるか」を確認する

業務自動化では、スクリプトが夜中に自動実行されることも多く、「フォルダがなかったからエラーで止まっていた」ことに気づくのが翌日…という事故が起きがちです。

そのため、コピー前にフォルダを作っておくテンプレートを覚えておくと安心です。

import os
import shutil

src = "data/report.txt"
dst_dir = "backup"
dst = os.path.join(dst_dir, "report_backup.txt")

# フォルダがなければ作る
os.makedirs(dst_dir, exist_ok=True)

shutil.copy(src, dst)
print("コピー完了:", dst)
Python

os.makedirs(..., exist_ok=True) は、「フォルダがなければ作る、あれば何もしない」という便利な関数です。
この一行をテンプレートとしてセットで覚えておくと、フォルダ関連のエラーをかなり減らせます。


例題①:毎日生成されるレポートを日付付きでバックアップする

シナリオのイメージ

例えば、毎日 data/report.csv が更新されるとします。
これを「日付付きのファイル名」で backup フォルダにコピーしておきたい、というのは典型的な業務自動化です。

最終的に、次のようなファイルが並ぶイメージです。

backup/report_2024-01-01.csv
backup/report_2024-01-02.csv
backup/report_2024-01-03.csv

コード例と解説

import os
import shutil
from datetime import date

src = "data/report.csv"

today = date.today().strftime("%Y-%m-%d")
dst_dir = "backup"
dst_name = f"report_{today}.csv"
dst = os.path.join(dst_dir, dst_name)

os.makedirs(dst_dir, exist_ok=True)

shutil.copy(src, dst)
print("バックアップ完了:", dst)
Python

このコードの流れを言葉で整理すると、こうなります。

まず、date.today().strftime("%Y-%m-%d") で今日の日付を "2024-03-14" のような文字列に変換しています。
次に、その日付を使って report_2024-03-14.csv のようなファイル名を組み立てています。
最後に、os.makedirs でバックアップフォルダを用意し、shutil.copy でコピーしています。

ここでの重要ポイントは、「コピー先のファイル名を自分で組み立てている」というところです。
業務自動化では、「元ファイル名をそのまま使う」のではなく、「日付」「バージョン」「担当者名」などを組み合わせて、意味のあるファイル名を作ることがよくあります。


例題②:特定の拡張子のファイルだけをまとめてコピーする

シナリオのイメージ

あるフォルダ inbox に、いろいろな種類のファイルが放り込まれているとします。
この中から「CSVファイルだけ」を csv_only フォルダにコピーしたい、というケースを考えます。

これは、「人が手作業で仕分けしていた作業」を自動化する、非常に現実的なパターンです。

コード例と解説

import os
import shutil

src_dir = "inbox"
dst_dir = "csv_only"

os.makedirs(dst_dir, exist_ok=True)

for name in os.listdir(src_dir):
    src_path = os.path.join(src_dir, name)

    # フォルダはスキップ(ファイルだけ対象)
    if not os.path.isfile(src_path):
        continue

    # 拡張子が .csv のものだけコピー
    if not name.lower().endswith(".csv"):
        continue

    dst_path = os.path.join(dst_dir, name)
    shutil.copy(src_path, dst_path)
    print("コピー:", src_path, "→", dst_path)
Python

このテンプレートには、業務自動化でよく使う考え方が詰まっています。

まず、os.listdir(src_dir) で「候補を全部取る」。
次に、os.path.isfile で「ファイルだけ」に絞る。
さらに、name.lower().endswith(".csv") で「拡張子が .csv のものだけ」に絞る。
最後に、shutil.copy でコピーする。

この「候補を全部取る → 条件で絞る → 処理する」という流れは、ファイルコピーに限らず、業務自動化の基本パターンとしてそのまま覚えてしまって構いません。


例題③:上書き事故を防ぐ「安全コピー」テンプレート

なぜ「上書きチェック」が大事なのか

shutil.copyshutil.copy2 は、コピー先に同名ファイルがあっても、何の警告もなく上書きします。
人間が手でやるときは「上書きしますか?」と聞いてくれますが、スクリプトは黙って実行します。

「昨日までのバックアップが全部上書きされて消えていた」という事故を防ぐために、「コピー先がすでに存在していたらどうするか」を自分で決めておく必要があります。

上書きしない安全コピーの例

import os
import shutil

def safe_copy(src, dst):
    if os.path.exists(dst):
        print("警告: すでに存在するためコピーをスキップしました →", dst)
        return

    # 必要ならフォルダを作成
    dst_dir = os.path.dirname(dst)
    if dst_dir:
        os.makedirs(dst_dir, exist_ok=True)

    shutil.copy(src, dst)
    print("コピー完了:", dst)

src = "data/report.txt"
dst = "backup/report.txt"

safe_copy(src, dst)
Python

この safe_copy 関数は、次のようなポリシーを持っています。

コピー先がすでに存在していたら、上書きせずにスキップする。
存在しない場合だけ、フォルダを作成してからコピーする。

業務によっては、「上書きする前にリネームして退避する」「上書きするが、ログに必ず記録する」など、別のポリシーを採用することもあります。
大事なのは、「何も考えずに上書きする」のではなく、「どう振る舞うかを自分で決めてコードに書く」ことです。


shutil.copy と shutil.copy2 の違いをどう使い分けるか

メタデータをどこまで気にするか

shutil.copyshutil.copy2 の違いは、「メタデータ(作成日時・更新日時など)をどこまでコピーするか」です。

shutil.copy
ファイルの中身とパーミッション(権限)をコピーする。作成日時などはあまり気にしない。

shutil.copy2
可能な限りメタデータもコピーする。より「元ファイルに近い状態」でコピーしたいときに使う。

例えば、「ログファイルを別の場所にバックアップするだけ」であれば、shutil.copy で十分なことが多いです。
一方、「監査用に、元ファイルと同じタイムスタンプで保管しておきたい」といった要件がある場合は、shutil.copy2 を選ぶ価値があります。

ただし、copy2 はメタデータを書き換える権限が必要になるため、環境によっては権限エラーが出やすくなることがあります。
「まずは確実に動かしたい」という段階では、copy から始めて、必要になったら copy2 に切り替える、という順番がおすすめです。


まとめ:ファイルコピーは「業務自動化の入り口」かつ「安全設計の練習場」

ここまで見てきたように、ファイルコピーは単なる「コピー」ではなく、業務自動化の中で次のような役割を持ちます。

元データを壊さないための「保険」としてのバックアップ。
人がやっていた仕分け作業を置き換える「自動仕分け」としてのコピー。
日付やバージョンを付けて履歴を残す「簡易バージョン管理」としてのコピー。

その中で、次のポイントを意識してコードを書くと、一気にプロっぽくなります。

コピー先がフォルダなのかファイルなのかを意識する。
フォルダがなければ os.makedirs(..., exist_ok=True) で用意する。
上書きするかどうかのポリシーを自分で決めて、コードに明示する。
必要に応じて shutil.copy2 でメタデータも含めてコピーする。

もしよければ、今あなたのPCにある「とりあえずバックアップを取りたいファイル」を1つ決めて、上のテンプレートの srcdst を書き換えて実行してみてください。
「自分のファイルが、Pythonのコード一行で安全にコピーされる」という感覚がつかめると、その先の自動化アイデアがどんどん出てくるはずです。

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