HOWTO · Python
Python でファイルの名前を変更する
この記事では、Python でファイルの名前を変更する方法について説明します
このページの内容
Python で1つのファイル名を変更するには、ソースと宛先のパスを指定して os.rename()、pathlib.Path.rename()、または shutil.move() を呼び出します。ファイルシステム上で名前を変更する場合は os.rename() または Path.rename() を使います。宛先が別のファイルシステム上にある可能性がある場合は shutil.move() を選びます。以下の例は一時ファイルを自分で作成するため、特定の作業ディレクトリに依存せず、プロジェクト内のファイルも変更しません。
os.rename() でファイル名を変更する
os.rename(source, destination) は、ソースのパスを宛先のパスに変更します。pathlib を使ってパスを組み立てると、現在のOSのパス規則に従って結合できます。この例では、一時ディレクトリ内にファイルを作成し、その中で名前を変更します。
この例を実行してください。
このセクションのコードと表示されるラベルや出力は英語のままです。
import os
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as folder:
source = Path(folder) / "draft.txt"
destination = Path(folder) / "final.txt"
source.write_text("Report", encoding="utf-8")
os.rename(source, destination)
print(destination.name, destination.read_text(encoding="utf-8"))
呼び出しが成功すると、戻り値は None です。相対パスはプロセスの現在の作業ディレクトリを基準に解釈されます。このディレクトリは、スクリプトが置かれているディレクトリとは異なることがあります。既知のディレクトリを基準にパスを組み立てると、こうした曖昧さを避けられます。
pathlib.Path.rename() でファイル名を変更する
Path.rename() は、ソースと宛先をパスオブジェクトとして扱いながら、同様にファイル名を変更します。with_name() は新しいファイル名を持つ同じ階層のパスを作りますが、それだけでファイル名が変更されるわけではありません。
このセクションのコードと表示されるラベルや出力は英語のままです。
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as folder:
source = Path(folder) / "draft.txt"
source.write_text("Report", encoding="utf-8")
destination = source.with_name("final.txt")
renamed_path = source.rename(destination)
print(renamed_path.name, renamed_path.read_text(encoding="utf-8"))
新しい場所を示す Path が戻り値として返されます。コード内ですでに Path でパスを扱っている場合は、この方法が適しています。OS上の名前変更に関する制約は os.rename() と同じです。
shutil.move() でファイル名を変更または移動する
shutil.move(source, destination) はパス形式の値を受け取り、宛先パスを文字列として返します。同じファイルシステム内で名前変更が可能なら、その操作を使います。別のファイルシステムへの移動では、ファイルをコピーしてからソースを削除する場合があるため、必ずしも原子的な名前変更にはなりません。
このセクションのコードと表示されるラベルや出力は英語のままです。
import shutil
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as folder:
source = Path(folder) / "draft.txt"
destination = Path(folder) / "final.txt"
source.write_text("Report", encoding="utf-8")
moved_to = shutil.move(source, destination)
print(Path(moved_to).name, Path(moved_to).read_text(encoding="utf-8"))
宛先に既存のディレクトリを指定すると、shutil.move() はソースのベース名を保ったまま、そのディレクトリ内に配置します。それ以外の場合、宛先は新しいパスとして扱われます。ディレクトリとファイル名を取り違える可能性があるときは、宛先の形式をよく確認してください。
パス、存在しないファイル、既存の宛先を扱う
ソースファイルが存在し、宛先の親ディレクトリが利用できる必要があります。ソースや親ディレクトリが見つからない場合、一般に FileNotFoundError が発生します。権限、開いているファイルに関する制約、その他のファイルシステムの状態によって、PermissionError や別の OSError が発生することもあります。アプリケーションで回復できる範囲の具体的なエラーだけを捕捉し、予期しない失敗は分かるようにしておきましょう。成功したように見せるメッセージを出すために、すべての例外を捕捉してはいけません。
宛先のファイルがすでに存在する場合の動作は、プラットフォームによって異なります。既存ファイルを置き換えるシステムもあれば、失敗するシステムもあります。Path.rename() も同じ基盤の規則に従います。shutil.move() も可能な場合は名前変更を使い、ファイルシステムをまたぐときはコピーと削除を行うため、どのプラットフォームやファイルシステムでも同じ上書き結果になるとは限りません。上書きを避けるには、移動前に宛先が存在しないことを確認します。ただし、確認後に操作するまでの間に別のプロセスが宛先を作成する可能性があります。より強い保証が必要なら、アプリケーションに適したOS固有の排他的操作を使ってください。
適切な方法を選ぶ
同じファイルシステム内で単純に名前を変更する場合、コードのほかの部分で pathlib を使っていれば Path.rename() を、文字列パスや os モジュールを使っていれば os.rename() を選びます。どちらも戻り値は None です。ファイルシステムをまたぐ可能性がある場合や、宛先にディレクトリを指定する動作が便利な場合は shutil.move() を使います。この方法は、移動先のパスを返します。いずれの方法でも有効なソースが必要で、複数段階のコピーと削除による移動が原子的になるわけではありません。ソースと宛先のパスを明示し、宛先がすでにある場合の扱いを決めたうえで、対応するプラットフォーム上でファイルシステムに依存する動作をテストしてください。