【Python】ファイルコピーを初心者向けに解説

はじめに

Pythonにはファイルコピーを行うための機能が標準ライブラリで用意されています。
初心者でも比較的簡単に扱えるため、日常的なファイル管理から業務の自動化まで、さまざまなシーンで役立ちます。

たとえば、システム保守の現場では、ログファイルを別のサーバーにバックアップとして定期的にコピーするケースがあります。
その際、Pythonのスクリプトを使って自動化することで、ヒューマンエラーを防ぎつつ、作業の手間を減らせるのが魅力です。

この記事では、Pythonでファイルコピーを行うさまざまな手法と、実際の開発での活用シーンを一緒に見ていきましょう。
実装例を交えながら解説していくので、「コードを書きたいけれど、一体どこから始めればいいのだろう?」と思っている皆さんの参考になれば嬉しいです。

この記事を読むとわかること

  • Pythonでファイルコピーを行うための基本的な方法
  • 実務での活用例(バックアップや大量のファイル操作など)
  • 標準ライブラリ(shutil、osなど)を使ったサンプルコード
  • ディレクトリごとのコピーや上書きに関する注意点

Pythonでファイルコピーを行うメリット

ここでは、そもそもなぜPythonでファイルコピーをするのか、そのメリットを具体的に見てみましょう。
単純なコマンド操作に比べて、プログラムとしての再利用性や自動化しやすさが挙げられます。

ファイルコピーとは

ファイルコピーとは、ひとつのファイルを別の場所に複製する作業のことです。
WindowsやMacなどのOS上であれば、マウス操作でドラッグ&ドロップするだけでも同様の操作ができます。
しかし、作業の自動化や大量のファイルを扱う場合は、Pythonのようなスクリプト言語で書く方が効率的です。

実務での活用シーン

ファイルコピーは、以下のように実務でよく使われます。
たとえばサーバーの運用保守で、特定の時刻に新規ファイルが生成される場合、そのファイルを自動的にバックアップ用フォルダへ移動または複製するという流れはよくあるはずです。
また、データ分析の現場でも、毎日生成されるCSVファイルを別フォルダにまとめる作業をPythonスクリプトで管理することがあります。

こうした場面では、Pythonのスクリプトを一度作ってしまえば、あとは定期実行できるのでとても便利です。
定期実行の仕組みを組み合わせることで、人的コストの削減にもつながります。

Pythonの標準ライブラリを使う利点

ファイルコピーの方法としては、シェルのコマンドを呼び出す方法もありますが、Pythonにはshutilモジュールなど便利な標準ライブラリが用意されています。
これを使うと、コードが短くシンプルになる点、そしてマルチプラットフォームで動く点が魅力です。

OSのコマンドに依存する方法では、WindowsとLinux間の互換性問題などが起きる場合もあります。
しかし、Pythonのライブラリを使えば、OSに依存しにくい形でファイルコピー処理を実装しやすくなります。

Pythonでファイルコピーを行う方法

ここからは、実際のコードを示しながら、具体的なファイルコピーの実装方法を解説します。
主に使用するのは、shutilモジュールとosモジュールです。

shutilを使う方法

shutilモジュールは、ファイルやディレクトリを扱うための便利な関数群を提供してくれます。
特にシンプルな使い方でありながら、Windows・Mac・Linux問わず動作してくれるため初心者にも扱いやすいです。

shutil.copy

最も基本的な関数が shutil.copy です。
元ファイルとコピー先のパスを指定するだけで、ファイルがコピーされます。

import shutil

# 元ファイルのパス
src_file = "test.txt"
# コピー先のファイルパス
dst_file = "backup/test_copy.txt"

shutil.copy(src_file, dst_file)

上の例では、同じファイル名を使う必要はありません。
test.txtbackup/test_copy.txtという名前でコピーすることができます。
この関数はファイルの内容だけをコピーし、メタデータ(ファイルの作成日時など)の完全な複製は行いません。

shutil.copy2

メタデータも含めてコピーを行いたい場合は、shutil.copy2 を使うと便利です。
作成日時やアクセス日時などの情報まで極力保持した状態でコピーしてくれます。

import shutil

src_file = "test.txt"
dst_file = "backup/test_copy_with_metadata.txt"

shutil.copy2(src_file, dst_file)

shutil.copy2は、実務でファイルをアーカイブしたりバックアップを取ったりするシーンでよく使われます。
必要に応じて使い分けると良いでしょう。

osモジュールを使う方法

osモジュールでもファイル操作は可能ですが、単純なファイルコピーを行う機能が直に備わっているわけではありません。
たとえば、os.systemを使ってシェルのコピーコマンドを実行する方法がありますが、OS固有のコマンドに依存してしまう可能性が高いです。

os.systemを使うかどうか

os.system("cp src_file dst_file") のように書けば、UNIX系では動作します。
しかし、Windowsではcopyコマンドに書き換えないといけませんし、その結果、マルチプラットフォームで動かすときにエラーが生じやすいです。

そのため、ファイルコピーだけに関しては、基本的にshutilモジュールを使うのがおすすめです。
osモジュールはパス操作などにはとても便利ですが、ファイルコピーのような処理はshutilのほうが安全でわかりやすいと言えるでしょう。

ディレクトリコピーの実例

ファイル単体ではなく、ディレクトリ全体をまるごとコピーしたい場合もあります。
こうした場面では、shutilの中でも複数の機能が役立ちます。

shutil.copytree

ディレクトリを丸ごとコピーするときは、shutil.copytree を使います。
この関数は非常に便利で、サブディレクトリやファイル構成をそのまま再帰的にコピーしてくれます。

import shutil

src_dir = "my_folder"
dst_dir = "backup/my_folder_copy"

shutil.copytree(src_dir, dst_dir)

これだけで、my_folderの中身を完全に複製できます。
ただし、コピー先のフォルダdst_dirがすでに存在しているとエラーになってしまいます。
もし既存フォルダがある場合は、別のフォルダ名を指定したり、事前に削除するなどの処理が必要です。

os.walkを使う方法

ディレクトリコピーを自分で制御したい場合は、os.walkを使う手段もあります。
os.walkは指定したディレクトリ以下のすべてのファイルとフォルダを走査してくれる関数です。

具体的には、下記のようにos.walkを使い、取得したファイルをひとつずつコピーする方法があります。
コピー対象を絞り込みたいときや、特定のファイル名・拡張子だけをコピーしたいときに便利です。

import os
import shutil

def copy_directory(src, dst):
    for root, dirs, files in os.walk(src):
        # 目的のディレクトリを作成
        relative_path = os.path.relpath(root, src)
        target_dir = os.path.join(dst, relative_path)
        os.makedirs(target_dir, exist_ok=True)

        # ファイルをコピー
        for file in files:
            src_file = os.path.join(root, file)
            dst_file = os.path.join(target_dir, file)
            shutil.copy2(src_file, dst_file)

# 使い方の例
copy_directory("my_folder", "backup/my_folder_copy")

このようにコードを書いておくと、必要に応じてフィルタリングやログ出力なども挟みやすくなります。
shutil.copy2 を使っているため、タイムスタンプなどのメタデータも維持しながらコピーできるのがポイントです。

ファイルコピー時の注意点とエラー対処

ファイルコピーはシンプルな操作のように見えますが、実際にはいくつか気をつけるべき点があります。
この章では、初心者がハマりやすいポイントと、それらを回避するための方法を解説します。

パスの扱い

Windowsは\(バックスラッシュ)、MacやLinuxは/(スラッシュ)をファイルパスに用います。
でも、Pythonのプログラムで文字列としてハードコーディングすると、OSごとにパス表記を変える必要があり、混乱を招くことがあります。

こうした問題を回避するには、os.path.joinpathlib.Pathを使ってパスを結合すると良いでしょう。

import pathlib

src = pathlib.Path("test_folder") / "test.txt"
dst = pathlib.Path("backup") / "test_backup.txt"

# WindowsでもMacでもLinuxでも動作しやすい
shutil.copy(src, dst)

パスを意識せずに記述できるので、マルチプラットフォームを意識するならpathlibはおすすめです。

エラー時の例外処理

ファイルが存在しない、あるいはディレクトリが読み取り専用になっていると、コピー時にエラーが発生します。
そうした場合はtry-exceptを使ってエラー処理を行います。

import shutil

try:
    shutil.copy("not_exist.txt", "backup/not_exist_copy.txt")
    print("コピーが完了しました。")
except FileNotFoundError:
    print("ファイルが存在しません。")
except PermissionError:
    print("ファイルの権限に問題があります。")
except Exception as e:
    print(f"想定外のエラーが発生しました: {e}")

エラーを適切に捕捉して、ログを取るなり再試行するなりすることで、システム障害を未然に防ぎやすくなります。
また、どのようなエラーが起きても一括して扱いたい場合は、except Exceptionで受けておくと便利です。

上書きに注意

コピー先に同名のファイルが存在する場合は、基本的に上書きされることになります。
大切なファイルを誤って消してしまわないように、事前に確認する処理を入れるほうが安全です。

import os
import shutil

def safe_copy(src, dst):
    if os.path.exists(dst):
        print("コピー先ファイルがすでに存在します。上書きしないように処理を中断します。")
        return
    shutil.copy(src, dst)

safe_copy("test.txt", "backup/test.txt")

このように一度存在チェックを行うか、ファイル名を別の形式にリネームして保存するなどの工夫もおすすめです。

大容量ファイルを扱うとき

コピー対象が数GBを超えるようなファイルになると、単純にshutil.copyshutil.copy2を使うだけでは時間がかかる場合があります。
しかし、Pythonだけで高速化を図るのは難しいことも多いので、ハードウェアの性能やネットワーク帯域といった外部要因も考える必要があります。

それでもPython側で工夫したいときは、バッファサイズを指定しながら部分的にファイルを読み書きする方法があります。
システムリソースを過度に消費しないよう、分割して読み取り・書き込みを行いながらファイルをコピーするわけです。

def copy_large_file(src, dst, buffer_size=1024*1024):
    with open(src, "rb") as f_src, open(dst, "wb") as f_dst:
        while True:
            chunk = f_src.read(buffer_size)
            if not chunk:
                break
            f_dst.write(chunk)

こうした手動のコピー処理は、ファイル進捗表示を実装したい場合にも役立ちます。
ただし、通常はshutil.copyでも十分な場面が多いので、必要に応じて使い分けるイメージです。

大容量ファイルをコピーするときは、ディスク容量やネットワーク帯域を十分に確保できているかも重要です。 誤ってストレージがいっぱいになると、システム全体に支障をきたすリスクがあります。

便利な追加テクニック

ファイルコピーと同時に、もうひと手間かけたいケースもあるでしょう。
たとえばコピー後にファイルを圧縮したり、ファイルの整合性をチェックしたりする場面です。

ファイルコピー後の圧縮

Pythonのzipfiletarfileモジュールを使って、コピーしたファイルを圧縮してから保管することも可能です。
一例として、コピー先フォルダをzip形式でまとめておくと、保管スペースの削減やファイル転送の高速化につながることがあります。

import shutil
import zipfile

# ディレクトリを丸ごとコピー
shutil.copytree("my_folder", "backup/my_folder_copy")

# その後、圧縮したい場合
with zipfile.ZipFile("backup/my_folder_copy.zip", "w", compression=zipfile.ZIP_DEFLATED) as new_zip:
    new_zip.write("backup/my_folder_copy/some_file.txt", arcname="some_file.txt")

ただし、ここではあくまで追加の作業として紹介しています。
最初から圧縮された状態でコピーしたいのであれば、ファイルの用途や環境に合わせて設計を変える必要があります。

ファイルサイズやハッシュ値を比較する

「ちゃんとコピーできているかどうか」を確認したい場合は、コピー前後のファイルサイズやハッシュ値をチェックする方法もあります。
Pythonのhashlibを使えば、ファイルのハッシュを計算することが可能です。

import hashlib

def calculate_sha256(file_path):
    sha256_hash = hashlib.sha256()
    with open(file_path,"rb") as f:
        for byte_block in iter(lambda: f.read(4096), b""):
            sha256_hash.update(byte_block)
    return sha256_hash.hexdigest()

コピー前後のファイルに対してこの関数を呼び、ハッシュ値が一致すれば問題なくコピーできている可能性が高いと判断できます。
実務の中では、バックアップ処理後の整合性確認に活用することがあるかもしれません。

実務で役立つ運用上のポイント

ファイルコピーのロジックを組み立てただけでは、運用を始めたときに思わぬトラブルが起こる可能性があります。
次のポイントを押さえておくと、よりスムーズに実務へ適用できるはずです。

エラーログの出力

システムが大きくなると、どこで失敗したのか追跡しにくくなることがあります。
そこで、エラーが起きたときにログファイルへ残すようにしておくと、問題解決の手がかりが増えます。

import logging
import shutil

logging.basicConfig(filename="copy.log", level=logging.ERROR)

def copy_with_logging(src, dst):
    try:
        shutil.copy2(src, dst)
    except Exception as e:
        logging.error(f"Failed to copy from {src} to {dst}: {e}")
        raise

このように、ログファイルにエラー内容を書き出しておけば、万一の際に原因を特定しやすくなります。

定期実行の仕組みとの連携

ファイルコピーのスクリプトを定期的に走らせたい場合、Windowsならタスクスケジューラ、Linuxならcronなどの仕組みを使います。
Python側での実装だけではなく、OSのスケジューリング機能と連携させることで、自動バックアップなどが簡単に実現できます。

このように、Pythonスクリプトの部分をしっかり作り込んだら、あとは運用環境に合わせて設定すればOKです。
初心者でも手順さえ押さえれば、そこまで難しい作業ではないでしょう。

バージョン管理とドキュメンテーション

運用中に「こうしたほうがいいかも」とコードを修正することは珍しくありません。
その際、Gitなどのバージョン管理ツールを使っておけば、変更の履歴が追跡しやすく、誤って古いバージョンへ巻き戻してしまうリスクも減ります。

ドキュメントを簡単にまとめておくと、チーム内での引き継ぎがスムーズになります。
どのフォルダをコピーして、どんなファイルをバックアップしているのかを共有できるようにしておくことをおすすめします。

よくある質問と対処法

ここでは、初心者の皆さんがファイルコピーに関して抱きがちな疑問をまとめます。

コピー先でファイル名が衝突するときはどうする?

たとえば、コピー先に同名のファイルが大量にある場合は、上書きリスクが大きくなります。
このときはファイル名を連番に変える、日付を付与する、サブディレクトリに分割するなどの方法が考えられます。
運用方針に合わせてファイル命名ルールを決めておくと安心です。

一部だけをコピーしたい場合は?

拡張子が.txtのファイルだけコピーするなど、一部のファイルだけ対象にしたいケースがあります。
この場合はos.listdiros.walkでファイル名を取得し、条件文で絞り込んだ上でshutil.copyを実行すればOKです。

遅いと感じるときはどうすればいい?

Pythonによるコピー速度が遅いと感じる場合、ハードディスクやネットワークの速度がネックになっていないか確認しましょう。
Pythonのコードでできる最適化は限られているので、まずはシステム全体のリソースをチェックするのが早道です。

まとめ

Pythonでファイルコピーを行う方法を紹介してきました。
初心者の方でも、標準ライブラリのshutilを使えばシンプルに実装できることが分かったのではないでしょうか。

この記事では、ファイル単体のコピーだけでなく、ディレクトリ全体のコピーやメタデータの扱い、エラー処理、そして実務での運用を念頭に置いたポイントなども解説しました。

単なるファイルコピーとはいえ、実務で使うとなると上書きリスクやバージョン管理、ログの取り方など、考慮すべき点が多いです。
しかし、しっかりと手順を踏んでコードを組み立てれば、バックアップ作業やファイル管理が確実かつ効率的に行えるようになるでしょう。

Pythonを活用してファイルコピーをスマートにこなせるようになれば、今後の開発や運用業務でも大いに役立つはずです。
ぜひ実際のプロジェクトや、ちょっとした日常のタスクで試してみてください。

Pythonをマスターしよう

この記事で学んだPythonの知識をさらに伸ばしませんか?
Udemyには、現場ですぐ使えるスキルを身につけられる実践的な講座が揃っています。