ユーニックス総合研究所

  • home
  • archives
  • python-copy-file

Pythonでファイルをコピーする方法4選: copyfile, copy, copy2, copytree

  • 作成日: 2021-06-02
  • 更新日: 2023-12-24
  • カテゴリ: Python

Pythonでファイルをコピーする方法

Pythonではライブラリを使うとファイルを簡単にコピーすることができます。
ライブラリはshutilという標準ライブラリを使います。

この記事ではshutilの関数を使ってファイルをコピーする方法を解説します。
結論から言うとファイルのコピーは↓のようにします。

import shutil  


shutil.copyfile('sample/src/file1.txt', 'sample/dst/file2.txt')  
shutil.copy('sample/src/file1.txt', 'sample/dst/file3.txt')  
shutil.copy2('sample/src/file1.txt', 'sample/dst/file4.txt')  
shutil.copytree('sample/src/', 'sample/dst/src')  
# sample/dst/  
# ├── file2.txt  
# ├── file3.txt  
# ├── file4.txt  
# └── src  
#     └── file1.txt  

具体的には↓を見ていきます。

  • 主要4関数の違い
  • copyfile()の使い方
  • copy()の使い方
  • copy2()の使い方
  • copytree()の使い方

関連記事

頭が悪い人のPythonのevalの使い方
頭がいい人のPythonのexitの使い方
自作関数read_fileでファイルを読み込み【ファイル入出力, コマンド】
状態遷移による文字列パースのテクニック【Python】
形態素解析で代名詞+助詞+名詞を文章から抜き出す【Python, 自然言語処理, Janome】

主要4関数の違い

copyfile(), copy(), copy2(), copytree()の違いを具体的に表にしてみました。

関数名 コピーするもの コピーの挙動
copyfile ファイル ファイル内容のみをコピーし、ファイルのパーミッション、メタデータをコピーしない。
copy ファイル ファイル内容をコピーし、パーミッションもコピーする。
copy2 ファイル ファイル内容をコピーし、パーミッションやメタデータ(作成日、更新日)もコピーするように努める。
copytree ディレクトリ ディレクトリを丸ごとコピーする。

とりあえず何でもかんでもコピーしたい場合はcopy2()を使っておけば良さそうです。
ただcopy2()も絶対的にメタデータのコピーが成功するという訳ではないみたいなので、その辺は注意が必要です。
それからできるだけ完璧にディレクトリをコピーしたい場合はcopytree()の引数(copy_function)にcopy2を指定すれば良さそうです。
メタデータやパーミッションが重要でない場合はcopyfile()のほうがcopystat()を呼び出さない分動作は早くなりそうです。

copyfile()の使い方

shutil.copyfile()は第1引数に指定されたファイルを第2引数にコピーします。

copyfile()の構造は↓のようになっています。

shutil.copyfile(src, dst, *, follow_symlinks=True)  

第2引数のdstは書き込み可能である必要があります。
dstが書き込み不可であった場合、copyfile()は例外OSErrorを送出します。
dstがすでに存在する場合は上書きされます。

第3引数のfollow_symlinksFalsesrcがシンボリックリンクであった場合、copyfile()srcの内容をコピーせずシンボリックリンクを作成します。

copyfile()copy()copy2()と違ってコピー時にファイルのパーミッションやメタデータを維持しません
そのため日付などはコピー元と異なる場合があります。

↓がサンプルコードです。

import shutil  


shutil.copyfile('sample/src/file1.txt', 'sample/dst/file2.txt')  

↑の場合sample/src/file1.txtというファイルがsample/dst/file2.txtにコピーされます。

copy()の使い方

shutil.copy()は第1引数に指定されたファイルを第2引数にコピーします。

copy()は↓のような構造になっています。

shutil.copy(src, dst, *, follow_symlinks=True)  

copy()copyfile()と同様に第3引数のfollow_symlinksFalsesrcがシンボリックだった場合は、単純にシンボリックリンクを作成します。

copy()はファイルの内容の他に、ファイルのパーミッションをコピーします。
ファイルの作成日や更新日などのメタデータはコピーしません

↓がサンプルコードです。

import shutil  


shutil.copy('sample/src/file1.txt', 'sample/dst/file2.txt')  

↑の場合もsample/src/file1.txtというファイルがsample/dst/file2.txtにコピーされます。

copy2()の使い方

shutil.copy2()は第1引数に指定されたファイルを第2引数にコピーします。

copy2()の構造は↓のようになっています。

shutil.copy2(src, dst, *, follow_symlinks=True)  

copy2()も第3引数にfollow_symlinksを持っていますが、これがFalsesrcがシンボリックリンクだった場合は、単純にシンボリックリンクが作成されます。

copy2()はメタデータをコピーしようとします。
メタデータとはファイルの作成日、更新日などのデータのことです。
copy2()はこれらのデータのコピーのために内部的にcopystat()を使います。

↓がサンプルコードです。

import shutil  


shutil.copy2('sample/src/file1.txt', 'sample/dst/file2.txt')  

↑の場合もsample/src/file1.txtというファイルがsample/dst/file2.txtにコピーされます。

copytree()の使い方

ディレクトリを丸ごとコピーしたい場合はcopytree()を使います。
copytree()は第1引数に指定されたディレクトリを第2引数にコピーします。

copytree()は↓のような構造になっています。

shutil.copytree(  
    src,  
    dst,  
    symlinks=False,  
    ignore=None,  
    copy_function=copy2,  
    ignore_dangling_symlinks=False,  
    dirs_exist_ok=False,  
)  

srcがコピー元でdstがコピー先です。
サンプルコードは↓です。

import shutil  


shutil.copytree('sample/src/', 'sample/dst/src')  

symlinksTrueの場合は、ディレクトリ内のシンボリックリンクは、そのままシンボリックリンクとしてコピーされます。
symlinksFalseの場合は、シンボリックリンクであっても中身をコピーして新しくディレクトリを作成します。

ignoreには関数を指定します。この関数の返り値のファイル名をcopytree()はコピー時に無視します。
この関数の第1引数には現在走査中のディレクトリを表すオブジェクト、第2引数にはディレクトリの内容を表すオブジェクトが渡されます。
この関数の挙動は↓のようなコードで確認することができます。

def ignore(dir_, lis):  
    print(dir_, lis)  
    return 'file1.txt'  

shutil.copytree('sample/src/', 'sample/dst/src', ignore=ignore)  

出力結果↓。

sample/src/ {'file1.txt', 'dir1', 'dir2'}  
<DirEntry 'dir1'> {'file1.txt', 'file2.txt'}  
<DirEntry 'dir2'> {'file1.txt', 'file2.txt'}  

↑のコードを実行するとsample/src以下のファイルがコピーされます。
そのときfile1.txtは除外してコピーされます。

copy_functionにはコピーで使用する関数を指定します。デフォルトではcopy2()です。
copyfile()を指定する場合は↓のようになり、

shutil.copytree('sample/src/', 'sample/dst/src', copy_function=shutil.copyfile)  

copy()を指定する場合は↓のようになります。

shutil.copytree('sample/src/', 'sample/dst/src', copy_function=shutil.copy)  

symlinksFalseで、シンボリックリンクが壊れている場合はコピーに失敗し例外がエラーリストに追加される場合がありますが、ignore_dangling_symlinksTrueに設定するとこのエラーが送出されなくなります。

dirs_exist_okTrueの場合、すでにディレクトリが存在する場合でもエラーが送出されなくなります。

copytree()はコピー先にすでにディレクトリが存在する場合は、dirs_exist_okが指定されている場合を除いてエラー(FileExistsError)が出力されます。

try:  
    shutil.copytree('sample/src/', 'sample/src')  
except FileExistsError as e:  
    print(e)  
    # [Errno 17] File exists: 'sample/src'  

おわりに

今回はPythonでファイルをコピーする方法を見てみました。
コピーはプログラムの基本ですが、Pythonではshutilを使うことで簡単に行うことができます。

🦝 < コピーがコピーを生み

🐭 < コピーの海……