ディレクトリ階層のコピーとは、あるディレクトリをコピー元として指定したときに、そのディレクトリとその下にあるディレクトリやファイルを階層ごと全てコピーすることだ。これにはshutil.copytree関数を使用する(以下、「shutil.」は省略して表記する)。
shutil.copytree(src, dst, ignore=None, copy_function=copy2)
srcで指定されるディレクトリ以下の階層構造を、dstで指定されるディレクトリにコピーする。ignoreにはコピーの対象としないファイルをshutil.ignore_patterns関数を用いて指定する。copy_functionにはコピーを行うのに使用する関数を指定する(デフォルトではshutil.copy2関数が使用される)。戻り値は、コピー先のディレクトリを表す文字列またはpathlib.Pathオブジェクト。
パラメーター | 説明 |
---|---|
src | コピー元のディレクトリ |
dst | コピー先のディレクトリ |
ignore | コピー対象としないファイル/ディレクトリを表すパターンを表すオブジェクト。shutil.ignore_pattern関数で作成できる。省略時はNoneが指定されたものとして、全てのファイル/ディレクトリがコピーされる |
copy_function | コピーに使用する関数を指定する(デフォルト値はcopy2関数) |
copytree関数のパラメーター |
以下に使用例を示す。まずは先ほど作成したfooディレクトリとその下にあるxxx.txtファイルをbarディレクトリにコピーしてみる。ファイル1つではつまらないので、ディレクトリも1つ追加して、それもコピーしてみよう。
Path('foo/foo2').mkdir() # fooディレクトリにfoo2ディレクトリを作成
shutil.copytree('foo', 'bar') # 存在しないディレクトリを指定
shutil.copytree('foo', 'bar') # 既存のディレクトリにコピーしようとして例外
ここでは同じ行を2回書いているが、最初の行ではbarディレクトリがないのでcopytree関数は成功する。しかし、2回目のcopytree関数は既に存在しているディレクトリを第2引数に指定しているので、こちらは例外となる。
では「ls -l bar」コマンドでbarディレクトリのファイルを表示してみよう。
xxx.txtファイルとfoo2ディレクトリがコピーされている。
次に、ディレクトリ階層に含まれるファイルを選択的にコピーするのに使える、パラメーターignoreの使用例を見ていこう。このパラメーターにglob形式のパターン(?、*などを使って表現したファイル/ディレクトリのパターン)を指定すると、それらにマッチするファイルがコピー対象から外される。
実際に試す前に、ファイルをもう1つ作っておこう。
Path('foo/yyy.py').write_text('print("hello")')
これでfooディレクトリにはxxx.txtファイルとyyy.pyファイルとfoo2ディレクトリが存在するようになる。ここから拡張子が「.txt」のもの以外をコピーしたいとする。つまり、パラメーターignoreには「.txt」を表す何かを渡せばよい。ここでは「*.txt」とすることで「xxx.txt」「aaa.txt」「somefile.txt」などに対応させればよい。ただし、実際にはパラメーターignoreには、「コピー対象外とするパターンをshutil.ignore_patterns関数の引数に列挙したもの」を渡す。そのため、「拡張子が.txt以外のもの」をコピーしたければ、copytree関数には次のような引数を記述する。
shutil.copytree('foo', 'baz', ignore=shutil.ignore_patterns('*.txt'))
このコードに続けて、「ls -l baz」コマンドを実行すると次のようになる。
上の画像を見ると、「*.txt」にマッチするxxx.txtファイルがコピーされていないのが分かる。
Copyright© Digital Advantage Corp. All Rights Reserved.