shutilモジュールが提供するmove関数を使って、ファイルやディレクトリの名前を変更したり、移動したりする方法を紹介する。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
import shutil
from pathlib import Path
foo = Path('foo.txt')
bar = Path('bar.txt')
foo.touch() # 準備としてファイルを作成
bar.touch() # 同上
# ファイルの名前変更
res = shutil.move('foo.txt', 'baz.txt')
print(res) # baz.txt:戻り値は変更後(移動後)の名前
# 既存のファイルの名前を指定
res = shutil.move('bar.txt', 'baz.txt') # UNIX:OK、Windows:OK
print(res) # baz.txt
# 既存のディレクトリの名前を指定するとファイルの移動になる
dir1 = Path('dir1')
dir1.mkdir()
res = shutil.move('baz.txt', 'dir1')
print(res) # dir1/baz.txt
# 移動先として存在しないファイルの名前を指定
dir2 = Path('dir2')
dir2.mkdir()
res = shutil.move('dir1/baz.txt', 'dir2/qux.txt')
print(res) # dir2/qux.txt
# 存在しないディレクトリが含まれているパスを移動先に指定すると例外
shutil.move('dir2/qux.txt', 'dir3/quux.txt') # FileNotFoundError
# ディレクトリの名前変更
res = shutil.move('dir1', 'dir3')
print(res) # dir3
# 既存ファイルの名前をdestに指定するとFileExistsError例外
shutil.move('dir3', 'dir2/qux.txt') # FileExistsError
# 変更後の名前として既存のディレクトリの名前を指定するとディレクトリが移動される
res = shutil.move('dir3', 'dir2') # ディレクトリの移動となる
print(res) # dir2/dir3
ファイルやディレクトリの名前を変更したり、別のディレクトリに移動したりするには幾つかの方法がある。
本稿では、このうちshutilモジュールを使用する方法を紹介する。
shutil.move関数の構文を以下に示す。
shutil.move(src, dest)
srcには名前変更/移動したいファイルやディレクトリを指定する。destには変更後の名前、または移動先のディレクトリを指定する。shutil.move関数は異なるファイルシステム間でのファイル/ディレクトリの移動時には、srcを(再帰的に)コピーした後にsrcを削除するが、ファイルのコピーで使用する関数をcopy_function引数に指定できる(が、本稿では説明を省略する)。なお、shutil.move関数では、srcとdestの両方に、pathlibモジュールで定義されているPathクラスのインスタンスを指定することもできる。
shutil.move関数は名前変更後/移動後のファイル/ディレクトリの名前を戻り値とする。
shutil.move関数は基本的に以下のように振る舞う。
移動元 | 移動先 | 動作 |
---|---|---|
ファイル | 存在しない名前 | 名前変更 |
ファイル | 存在するファイルの名前 | 名前変更(上書き) |
ファイル | 存在するディレクトリの名前 | 移動 |
ディレクトリ | 存在しない名前 | 名前変更 |
ディレクトリ | 存在するファイルの名前 | FileExistsError |
ディレクトリ | 存在するディレクトリの名前 | 移動 |
shutil.move関数の動作 |
ファイルの名前を変更するにはshutil.move関数に、名前を変更したファイルの名前と変更後の名前を指定する。以下に例を示す。
import shutil
from pathlib import Path
foo = Path('foo.txt')
bar = Path('bar.txt')
foo.touch() # 準備としてファイルを作成
bar.touch() # 同上
# ファイルの名前変更
res = shutil.move('foo.txt', 'baz.txt')
print(res) # baz.txt:戻り値は変更後(移動後)の名前
この例ではfoo.txtとbar.txtという2つのファイルを作成してから、「shutil.move('foo.txt', 'baz.txt')」としてfoo.txtの名前を「baz.txt」に変更している。その戻り値は変更後のファイルの名前なので、最後のprint関数呼び出しでは「baz.txt」が出力される。
既存ファイルの名前へ、ファイル名を変更しようとする例を以下に示す。
res = shutil.move('bar.txt', 'baz.txt') # UNIX:OK、Windows:OK
print(res) # baz.txt
osモジュールのrename関数やpathlibモジュールのPath.renameインスタンスメソッドを使ってこのようなファイル名の変更を行おうとすると、UNIXでは既存ファイルが上書きされ、WindowsではFileExistsError例外が発生する。しかし、shutil.move関数を使うと、どちらのプラットフォームでも既存のファイルが上書きされる。
destにディレクトリの名前を指定すると、srcに指定したファイルがdestに指定したディレクトリの直下に移動する。以下に例を示す。
dir1 = Path('dir1')
dir1.mkdir() # dir1ディレクトリを作成
res = shutil.move('baz.txt', 'dir1') # destにディレクトリの名前を指定
print(res) # dir1/baz.txt:baz.txtファイルがdir1ディレクトリの直下に移動された
この例ではdir1ディレクトリを作成した後、「shutil.move('baz.txt', 'dir1')」とdestにこのディレクトリの名前を指定している。そのため、上で名前変更したbaz.txtファイルはdir1ディレクトリに移動する。この結果、shutil.move関数は変更後の名前として「dir1/baz.txt」を返す。
ディレクトリの名前ではなく、ディレクトリを含んだ新しいファイル名をdestに渡してもファイルがそのディレクトリに移動する。
dir2 = Path('dir2')
dir2.mkdir()
res = shutil.move('dir1/baz.txt', 'dir2/qux.txt')
print(res) # dir2/qux.txt
この例では、dir2ディレクトリを作成して、上でdir1ディレクトリに移動したbaz.txtファイルをdir2ディレクトリに「qux.txt」という名前で移動している。
なお、移動先として存在しないディレクトリを含んだパスを渡すと例外が発生する。
shutil.move('dir2/qux.txt', 'dir3/quux.txt') # FileNotFoundError
これは上で移動したdir2/qux.txtファイルをdir3ディレクトリにquux.txtとして移動しようとしているが、dir3ディレクトリがないのでFileNotFoundError例外が発生する。
ディレクトリの名前変更はファイルの名前変更と同様、destに存在しないファイル/ディレクトリの名前を指定する。
res = shutil.move('dir1', 'dir3')
print(res) # dir3
ここではdir1ディレクトリの名前を「dir3」に変更しようとしている。「dir3」という名前のディレクトリやファイルは存在していないので、これは成功する。
既に存在しているファイルの名前をdestに指定すると、FileExistsError例外が発生する。
shutil.move('dir3', 'dir2/qux.txt') # FileExistsError
ここでは、上で名前を変更したdir3ディレクトリの名前を「dir2/qux.txt」に変更しようとしている。「dir2/qux.txt」は上で名前変更したファイルの名前で既に存在しているので、FileExistsError例外が発生する。
destに既存のディレクトリの名前を指定すると、ディレクトリがそこに移動する。以下に例を示す。
res = shutil.move('dir3', 'dir2') # ディレクトリの移動となる
print(res) # dir2/dir3
Copyright© Digital Advantage Corp. All Rights Reserved.