[解決!Python]ファイルやディレクトリを名前変更/移動するには:pathlibモジュール編解決!Python

pathlibモジュールが提供するPath.renameメソッドを使って、ファイルやディレクトリの名前を変更したり、移動したりする方法を紹介する。

» 2022年07月20日 05時00分 公開
[かわさきしんじDeep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「解決!Python」のインデックス

連載目次

from pathlib import Path

# ファイルの名前変更
foo = Path('foo.txt')
foo.touch()
bar = Path('bar.txt')
bar.touch()

# 存在しないファイルの名前に変更
baz = foo.rename('baz.txt')
print(baz)  # baz.txt:renameメソッドは変更後のファイルのパスを返す

# 既存のファイルの名前に変更
tmp = baz.rename(bar)  # UNIX:OK、Windows:FileExistsError

# ファイルの移動
a = Path('a')
a.mkdir()

a_bar = bar.rename('a/bar.txt')
#a_bar = bar.rename(Path(a, bar))

a_bar.rename('a/b/bar.txt'# FileNotFoundError

# ディレクトリの名前変更
dir0 = Path('dir1/dir2/dir3')
dir0.mkdir(parents=True)

dir1 = Path('dir1')
dir4 = dir1.rename('dir4')

# 既存ディレクトリの名前に変更しようとした場合
dir5 = Path('dir5')
dir5.mkdir()
dir5 = dir4.rename(dir5)  # Windows:FileExistsError

# 空でないディレクトリの名前に変更しようとした場合
dir6 = Path('dir6')
dir7 = Path(dir6, 'dir7')
dir7.mkdir(parents=True)
dir5.rename(dir6)  # UNIX:OSError、Windows:FileExistsError

# ディレクトリの移動
dir5.rename('dir6/dir7/dir5')


ファイルやディレクトリの名前を変更したり、移動したりする方法

 ファイルやディレクトリの名前を変更したり、別のディレクトリに移動したりするには幾つかの方法がある。

 本稿では、このうちpathlibモジュールを使用する方法を紹介する。

Path.renameインスタンスメソッド

 pathlibモジュールで定義されているPathクラスのインスタンス(コードを実行するプラットフォームに応じて、通常はPosixPathクラスのインスタンスかWindowsPathクラスのインスタンスのどちらかとなる)にはrenameメソッドがある。このメソッドの構文を以下に示す。

from pathlib import Path

p = Path(……)
target = Path(……)

p.rename(target)


 引数は1つだけで、そのオブジェクトが表しているパスの「新しい名前となる文字列かPathオブジェクト」を指定する。新しい名前として、ディレクトリを含む文字列またはPathオブジェクトを渡せば、そのファイル/ディレクトリが移動することになる。戻り値は、変更後のパスを表すPathオブジェクトとなる。

 このメソッドは内部的にはosモジュールで定義されているrename関数を使用しているので(pathlib.pyのソースコードを参照)、その振る舞いもos.rename関数と同様だ。上の「p.rename(target)」は実質的には「os.rename(p, target)」と等価である。

 os.rename関数を内部で使用しているので、UNIX系統のOSとWindowsでは振る舞いが異なる。Windowsではtargetに既存のファイルやディレクトリを指定すると常にFileExistsError例外が発生する。

移動元 移動先 UNIX Windows
ファイル 存在しない 成功 成功
ファイル ファイル 成功 FileExistsError
ファイル ディレクトリ IsADirectoryError FileExistsError
ディレクトリ 存在しない 成功 成功
ディレクトリ ファイル NotADirectoryError FileExistsError
ディレクトリ ディレクトリ(空) 成功 FileExistsError
ディレクトリ ディレクトリ(空ではない) OSError FileExistsError
Path.renameインスタンスメソッドの動作

ファイルの名前変更

 以下に簡単な例を示す。

from pathlib import Path

foo = Path('foo.txt')
foo.touch()
bar = Path('bar.txt')
bar.touch()

baz = foo.rename('baz.txt')
print(baz)  # baz.txt:renameメソッドは変更後のファイルのパスを返す


 この例では、fooとbarという2つのPathオブジェクトがあり、カレントディレクトリにあるfoo.txtファイルとbar.txtをそれぞれが表している(実際、touchメソッドを呼び出してそれらのファイルを作成している)。

 そして、fooオブジェクトのrenameメソッドを呼び出して、このオブジェクトが表しているファイル(foo.txt)の名前を「baz.txt」に変更している。ここではPathオブジェクトではなく文字列をrenameメソッドに渡している。また、戻り値は、変更後のファイル「baz.txt」を表すPathオブジェクトなので、print関数にこれを渡すと「baz.txt」と表示される。

 既に述べたが、既存ファイルの名前をtargetに指定した場合、UNIX系統のOSでは既存ファイルは上書きされる。WindowsではFileExistsError例外が発生する。上の例ではfoo.txtとbar.txtの2つのファイルを作成して、foo.txtの名前をbaz.txtに変更した。ここで、baz.txtの名前をbar.txtに変更してみよう。

tmp = baz.rename(bar)  # UNIX:OK、Windows:FileExistsError


 この例では、先ほどの「baz = foo.rename('baz.txt')」行で得られた、名前変更後のファイルのパスを表すオブジェクトbazを使って、renameメソッドを呼び出している。引数には、文字列ではなく、先ほど作成したbar.txtファイルを表すbarオブジェクトを渡している点にも注意しよう。

 UNIXではこれは成功してファイル名が変更されるが、WindowsではFileExistsError例外が発生する。以下はWindows上で動作するVisual Studio Code(以下、VS Code)から上記のコードを実行したところだ。

Windowsでは変更後の名前に既存ファイルの名前を指定すると例外となる Windowsでは変更後の名前に既存ファイルの名前を指定すると例外となる

 変更後の名前としてtargetに既存ディレクトリの名前を指定すると、例外の種類は異なるがUNIXでもWindowsでもエラーとなる。

ファイルの移動

 ファイルを移動するには、targetにディレクトリを含んだパスを文字列かPathオブジェクトの形で指定する。以下に例を示す。

a = Path('a')
a.mkdir()

a_bar = bar.rename('a/bar.txt')
#a_bar = bar.rename(Path(a, bar))


 この例では、カレントディレクトリに「a」というディレクトリを作成し、そこにbar.txtファイルを移動している。最後にあるコメントアウトされた行を見ると分かるが、aディレクトリを表すPathオブジェクト、bar.txtファイルを表すbarオブジェクトから作成したPathオブジェクト(これはa/bar.txtを表す)を渡すといったことも可能だ。

 targetに指定した文字列やPathオブジェクトが存在しないディレクトリを含んでいる場合には例外が発生する。

a_bar.rename('a/b/bar.txt'# FileNotFoundError


 これは先の例でaディレクトリに移動したb.txtファイル、つまりa/b.txtを表すオブジェクトをaディレクトリの下にあるbディレクトリの下に移動しようとしている。しかし、a/bディレクトリはないのでFileNotFoundError例外が発生している。

ディレクトリの名前変更

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。