この記事ではPythonのディレクトリ(フォルダ)を丸ごとコピーする関数『shutil.copytree()』について、
shutil.copytree()
とはshutil.copytree()
の構文shutil.copytree()
の使い方- ディレクトリを新規のディレクトリにコピーする方法
- ディレクトリを既存のディレクトリにコピーする方法
shutil.copytree()
のオプションsymlinks
引数ignore
引数copy_function
引数ignore_dangling_symlinks
引数dirs_exist_ok
引数
などをサンプルコードを用いて分かりやすく説明するように心掛けています。ご参考になれば幸いです。
shutil.copytree()とは
shutil.copytree()
は、Pythonの標準ライブラリshutil
に含まれる関数で、ディレクトリ(フォルダ)とその内容を再帰的にコピーするために使用されます。コピー元ディレクトリ内のすべてのファイルとサブディレクトリがコピーされます。
後ほどshutil.copytree()
の構文や使い方について詳しく説明しますが、まず以下に示す簡単なサンプルコードを見てみましょう。
import shutil
# コピー元ディレクトリパス
src_dir = 'testdir/dir1'
# コピー先ディレクトリパス
dst_dir = 'testdir/dir2'
# shutil.copytree()でtestdir/dir1ディレクトリの中身を丸ごとtestdir/dir2ディレクトリにコピー
shutil.copytree(src_dir, dst_dir)
上記のサンプルコードでは、testdir/dir1
ディレクトリをtestdir/dir2
ディレクトリにコピーしています。shutil.copytree(src_dir, dst_dir)
は、コピー元のディレクトリsrc_dir
の内容をコピー先のディレクトリdst_dir
に再帰的にコピーします。この操作により、testdir/dir1
ディレクトリ内のすべてのファイルとサブディレクトリがtestdir/dir2
ディレクトリに複製されます。
公式ドキュメント
shutil.copytree()
の公式ドキュメントのリンクを以下に示します。
この記事ではshutil.copytree()
の「使い方」や「オプション」についてできる限り分かりやすく説明しています。これらの関数の詳細を知りたい方は、公式ドキュメントをご覧ください。
shutil.copytree()の構文
shutil.copytree()
の構文を以下に示します。
構文
shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=shutil.copy2, ignore_dangling_symlinks=False, dirs_exist_ok=False)
shutil.copytree()
の引数と返り値を以下に示します。
引数
src
- コピー元のディレクトリパスです。
dst
- コピー先のディレクトリパスです。新規に作成されるディレクトリパスを指定します。
- コピー先ディレクトリが既に存在する場合にはエラーになりますが、引数
dirs_exist_ok
をTrue
に設定すると、エラーが発生しなくなります。
symlinks
(省略可能)- シンボリックリンクをコピーするかどうかを指定します。デフォルトは
False
です。
- シンボリックリンクをコピーするかどうかを指定します。デフォルトは
ignore
(省略可能)- コピー対象外とするファイルを指定するための関数を指定します。
copy_function
(省略可能)- ファイルをコピーするために使用する関数を指定します。デフォルトは
shutil.copy2
です。
- ファイルをコピーするために使用する関数を指定します。デフォルトは
ignore_dangling_symlinks
(省略可能)- ぶら下がりシンボリックリンクを無視するかどうかを指定します。デフォルトは
False
です。
- ぶら下がりシンボリックリンクを無視するかどうかを指定します。デフォルトは
dirs_exist_ok
(省略可能)- コピー先ディレクトリが存在する場合にエラーを発生させないかどうかを指定します。デフォルトは
False
です。
- コピー先ディレクトリが存在する場合にエラーを発生させないかどうかを指定します。デフォルトは
返り値(戻り値)
- コピー先ディレクトリのパスを返します。
shutil.copytree()の使い方
以下のディレクトリ構造とします。
testdir/
├── dir1/
│ ├── subdir/
│ │ └── file1.txt
│ └── file2.txt
└── dir2/
このディレクトリ構成で、shutil.copytree()
について、以下に示している使い方をこれから説明します。
- ディレクトリを新規のディレクトリにコピーする方法
- ディレクトリを既存のディレクトリにコピーする方法
上記の使い方について順番に説明します。
ディレクトリを新規のディレクトリにコピーする方法
shutil.copytree()
の第2引数dst
に新規のディレクトリパス(存在しないディレクトリのパス)を指定すると、コピー元のディレクトリsrc
の中身を丸ごと、新規のディレクトリパスdst
の中にコピーします。
サンプルコード
import shutil
src_dir = 'testdir/dir1'
dst_dir = 'testdir/dir3'
shutil.copytree(src_dir, dst_dir)
上記のサンプルコード実行後のディレクトリ構成
testdir/
├── dir1/
│ ├── subdir/
│ │ └── file1.txt
│ └── file2.txt
├── dir2/
└── dir3/
├── subdir/
│ └── file1.txt
└── file2.txt
ディレクトリを既存のディレクトリにコピーする方法
shutil.copytree()
の第2引数dst
に既存のディレクトリパス(存在するディレクトリのパス)を指定すると、デフォルトではエラーになります。この場合には、引数dirs_exist_ok
をTrue
にするとエラーになりならず、コピー元のディレクトリsrc
の中身を丸ごと、既存のディレクトリパスdst
の中にコピーすることができます(コピー先に同名のファイルがある場合はコピー元のファイルで上書きされます)。
まず、dirs_exist_ok
を指定しない場合(またはFalse
を指定した場合)のサンプルコードを以下に示します。
サンプルコード
import shutil
src_dir = 'testdir/dir1'
dst_dir = 'testdir/dir2'
shutil.copytree(src_dir, dst_dir)
エラーメッセージ
FileExistsError: [WinError 183] 既に存在するファイルを作成することはできません。: 'testdir/dir2'
dirs_exist_ok
をTrue
にすると、既存のディレクトリパス(存在するディレクトリのパス)にコピーすることができます。サンプルコードを以下に示します。
サンプルコード
import shutil
src_dir = 'testdir/dir1'
dst_dir = 'testdir/dir2'
# 第2引数dstに既存のディレクトリパスを指定してもエラーを発生させない
shutil.copytree(src_dir, dst_dir, dirs_exist_ok=True)
上記のサンプルコード実行後のディレクトリ構成
testdir/
├── dir1/
│ ├── subdir1/
│ │ └── file1.txt
│ └── file2.txt
└── dir2/
├── subdir1/
│ └── file1.txt
└── file2.txt
中間ディレクトリが既に存在するディレクトリの場合
以下に示すように第2引数dst
に指定するディレクトリパスにおいて、中間ディレクトリが既に存在するディレクトリの場合は、エラーにならず、コピー元のディレクトリsrc
の中身を丸ごと、dst
の中にコピーすることができます。
サンプルコード
import shutil
src_dir = 'testdir/dir1'
dst_dir = 'testdir/dir2/dir1_copy' # dir2は既に存在するディレクトリ(中間ディレクトリ)
shutil.copytree(src_dir, dst_dir)
上記のサンプルコード実行後のディレクトリ構成
testdir/
├── dir1/
│ ├── subdir1/
│ │ └── file1.txt
│ └── file2.txt
└── dir2/
└── dir1_copy/
├── subdir1/
│ └── file1.txt
└── file2.txt
shutil.copytree()のオプション
shutil.copytree()
に使用できる以下のオプションについて順番に詳しく説明します。
symlinks
引数ignore
引数copy_function
引数ignore_dangling_symlinks
引数dirs_exist_ok
引数
symlinks引数
symlinks
は、シンボリックリンクをコピーするかどうかを指定する引数です。デフォルトはFalse
であり、この場合、シンボリックリンク自体をコピーせず、リンク先のファイルやディレクトリをコピーします。True
を指定すると、シンボリックリンク自体をコピーします。
以下のディレクトリ構成とします(link
がシンボリックリンクであり、somefile
を参照しています)。
testdir/
├── dir1/
│ ├── subdir/
│ │ └── file1.txt
│ ├── file2.txt
│ └── link -> ../somefile
└── dir2/
サンプルコード
import shutil
src_dir = 'testdir/dir1'
dst_dir = 'testdir/dir3'
shutil.copytree(src_dir, dst_dir, symlinks=True)
上記のサンプルコード実行後のディレクトリ構成
testdir/
├── dir1/
│ ├── subdir/
│ │ └── file1.txt
│ ├── file2.txt
│ └── link -> ../somefile
└── dir3/
├── subdir/
│ └── file1.txt
├── file2.txt
└── link -> ../somefile
シンボリックリンクlink
がコピーされていることが確認できます。symlinks=False
(デフォルト設定)で実行した場合、リンク先のファイルがコピーされるので、リンク自体はコピーされません。
ignore引数
ignore
は「コピー対象外とするファイルを指定するための関数」を指定する引数です。この関数はディレクトリ内のファイル名のリストを受け取り、無視するファイル名のリストを返します。
以下のディレクトリ構成とします。
testdir/
├── dir1/
│ ├── subdir/
│ │ └── file1.txt
│ ├── file2.txt
│ └── file2.jpg
└── dir2/
以下のサンプルコードでは、.txt
で終わるファイル(拡張子がtxt
のファイル)をコピー対象外としています。
サンプルコード
import shutil
def ignore_files(dir, files):
return [f for f in files if f.endswith('.txt')]
src_dir = 'testdir/dir1'
dst_dir = 'testdir/dir3'
shutil.copytree(src_dir, dst_dir, ignore=ignore_files)
上記のサンプルコード実行後のディレクトリ構成
testdir/
├── dir1/
│ ├── subdir/
│ │ └── file1.txt
│ ├── file2.txt
│ └── file2.jpg
├── dir2/
└── dir3/
├── subdir/
└── file2.jpg
ignore_patterns()関数
ignore
引数にはshutil.ignore_patterns()
を指定することもできます。shutil.ignore_patterns()
には、glob
形式のパターンを複数指定します。指定したパターンに一致するファイルやディレクトリをコピー対象外とすることができます。
以下のディレクトリ構成とします。
testdir/
├── dir1/
│ ├── subdir/
│ │ └── file1.txt
│ ├── file2.txt
│ └── file2.jpg
└── dir2/
このサンプルコードでは、.txt
で終わるファイル(拡張子がtxt
のファイル)とsubdir
をコピー対象外としています。
サンプルコード
import shutil
src_dir = 'testdir/dir1'
dst_dir = 'testdir/dir3'
shutil.copytree(src_dir, dst_dir, ignore=shutil.ignore_patterns('*.txt', 'subdir'))
上記のサンプルコード実行後のディレクトリ構成
testdir/
├── dir1/
│ ├── subdir/
│ │ └── file1.txt
│ ├── file2.txt
│ └── file2.jpg
├── dir2/
└── dir3/
└── file2.jpg
copy_function引数
copy_function
は「ファイルをコピーするために使用する関数」を指定する引数です。デフォルトは shutil.copy2
であり、可能な限りメタデータもコピーします。メタデータをコピーしたくない場合には、copy_function
引数でshutil.copy()
を指定します。
サンプルコード
import shutil
import os
src_dir = 'testdir/dir1'
dst_dir = 'testdir/dir3'
# ファイル名を'file2.txt'に修正
shutil.copytree(src_dir, dst_dir, copy_function=shutil.copy)
print(os.path.getmtime('testdir/dir1/file2.txt') == os.path.getmtime('testdir/dir3/file2.txt'))
# False ← shutil.copy()の場合はコピーしたファイルの更新日時はコピーした時刻になるため
copy_function
引数を指定しない場合には、shutil.copy2
を用いてファイルがコピーされるため、可能な限りメタデータもコピーされ、コピーしたファイルの更新日時は元のファイルと同じになります。
サンプルコード
import shutil
import os
src_dir = 'testdir/dir1'
dst_dir = 'testdir/dir3'
# ファイル名を'file2.txt'に修正
shutil.copytree(src_dir, dst_dir)
# コピー元とコピー先の正しいパスを指定
print(os.path.getmtime('testdir/dir1/file2.txt') == os.path.getmtime('testdir/dir3/file2.txt'))
# True ← shutil.copy2()の場合はファイルの更新日時は元のファイルと同じであるため
あわせて読みたい
続きを見るshutil.copy()
とshutil.copy2()
については下記の記事で詳しく説明しています。興味のある方は下記のリンクからぜひチェックをしてみてください。 【Python】ファイルをコピーする方法!shutil.copy()とshutil.copy2()の使い方
ignore_dangling_symlinks引数
ignore_dangling_symlinks
はぶら下がりシンボリックリンクを無視するかどうかを指定する引数です。デフォルトは False
です。なお、ぶら下がりシンボリックリンク(dangling symlink)は、リンク先が存在しないシンボリックリンクです。通常のシンボリックリンクは、リンク元がリンク先のファイルやディレクトリを参照しますが、リンク先が削除されたり移動された場合、シンボリックリンクがぶら下がり状態(dangling)になります。
以下のディレクトリ構成とします。broken_link
がぶら下がりシンボリックリンクです。
testdir/
├── dir1/
│ ├── subdir/
│ │ └── file1.txt
│ ├── file2.txt
│ └── broken_link -> non_existent_file
└── dir2/
以下のサンプルコードでは、ignore_dangling_symlinks=True
を設定することで、ぶら下がりシンボリックリンクが存在しても、コピーが実行されるようにしています(ら下がりシンボリックリンクもそのままコピーされます)。False
に設定されている場合、broken_link
のようなぶら下がりシンボリックリンクが存在するとエラーが発生します。
サンプルコード
import shutil
src_dir = 'testdir/dir1'
dst_dir = 'testdir/dir3'
shutil.copytree(src_dir, dst_dir, ignore_dangling_symlinks=True)
上記のサンプルコード実行後のディレクトリ構成
testdir/
├── dir1/
│ ├── subdir/
│ │ └── file1.txt
│ ├── file2.txt
│ └── broken_link -> non_existent_file
├── dir2/
└── dir3/
├── subdir/
│ └── file1.txt
├── file2.txt
└── broken_link -> non_existent_file
dirs_exist_ok引数
dirs_exist_ok
はコピー先ディレクトリが存在する場合にエラーを発生させないかどうかを指定する引数です。デフォルトはFalse
です。デフォルトでは、コピー先ディレクトリが存在するとFileExistsError
が発生します。True
に設定すると、エラーが発生しなくなります。
サンプルコード
import shutil
src_dir = 'testdir/dir1'
dst_dir = 'testdir/dir2'
# 第2引数dstに既存のディレクトリパスを指定してもエラーを発生させない
shutil.copytree(src_dir, dst_dir, dirs_exist_ok=True)
本記事のまとめ
この記事ではPythonのディレクトリを丸ごとコピーする関数『shutil.copytree()』について、以下の内容を説明しました。
shutil.copytree()
とはshutil.copytree()
の構文shutil.copytree()
の使い方- ディレクトリを新規のディレクトリにコピーする方法
- ディレクトリを既存のディレクトリにコピーする方法
shutil.copytree()
のオプションsymlinks
引数ignore
引数copy_function
引数ignore_dangling_symlinks
引数dirs_exist_ok
引数
お読み頂きありがとうございました。