ファイルやディレクトリの名前を変更するには、osモジュールではos.rename関数、os.renames関数、os.replace関数を使用する。PathクラスではPath.renameメソッドを使用する(os.replace関数に対応するPath.replace関数もあるが本稿では省略する)。
Path.rename(target)
パスで表されるファイルまたはディレクトリの名前(Path.name属性で得られる部分)をtargetに変更する。targetには文字列またはPathオブジェクトを指定する。
| パラメーター | 説明 |
|---|---|
| target | 変更後の名前 |
| Path.renameメソッドのパラメーター | |
targetに既存のファイルを指定した場合、targetが表すファイルはパスで表されるファイルまたはディレクトリで警告なしに置き換えられる。targetが既存のディレクトリを表している場合、ファイルの名前を変更しようとしているのであれば、例外が発生する(UNIX/Windows共通)。一方、ディレクトリの名前を変更しようとしているのであれば、UNIXでは、元のパスのname属性で得られる名前(foo/barであればbar)が、targetという名前に置き換えられる。Windowsではtargetが既存のディレクトリを表しているのであれば、例外が発生する。このようにOSごとに振る舞いが異なる点には注意しよう。
以下に使用例を示す。
Path('a.txt').touch() # カレントディレクトリにa.txtファイルを作成
Path('b.txt').touch() # カレントディレクトリにb.txtファイルを作成
Path('a.txt').rename('c.txt')
print('a.txt?', Path('a.txt').exists())
print('c.txt?', Path('c.txt').exists())
Path('c.txt').rename('b.txt') # 既存のファイルを書き換え
print('c.txt?', Path('c.txt').exists())
print('b.txt?', Path('b.txt').exists())
Path('b.txt').rename('xxx') # 例外
以下に実行結果を示す。
テキストファイルを全く新しいファイル名に変更したり、既存のファイルの名前に変更したり(上書き)して、ファイルの存在確認を行っているので、その結果と、最後の行でテキストファイルの名前を既存のディレクトリの名前に変更しようとして例外が発生していることに注目されたい。
次にファイルの存在確認、Path.touchメソッドによるファイルの作成、ファイルかどうかの確認、ディレクトリかどうかの確認、Pathクラスを使ったファイルの読み書きについて見てみよう。
Pathクラスのインスタンスが実際に存在するファイルやディレクトリなどであるかは、Path.existsメソッドを使って調べられる。これはos.path.exists関数に対応するものだ。パスが存在すればTrueが、存在しなければFalseが返送される。
使用例を以下に示す。
print('b.txt?', Path('b.txt').exists()) # 先ほど作成したb.txtファイル
print('nonexists.txt?', Path('nonexist.txt').exists()) # 存在しないパス
実行結果を以下に示す。
Path.touchメソッドは、パスが表しているファイルを新規に作成するか、それが既に存在していれば、そのタイムスタンプを現在の日時に更新する。本稿ではパラメーターを指定しないので、基本構文を省略する(興味のある方はPythonのドキュメント「Path.touch()」を参照されたい)。
UNIXの世界では、テストなどの目的で(中身は空でよいので)ファイルを作成したいというときには、ファイルのタイムスタンプを変更する目的で作られたtouchコマンドがよく使われている。Path.touchメソッドは、そうした習慣に従って作られたのかもしれない。
前回は「os.system('echo ……')」のようにしてテスト用の使い捨てファイルを作成していたが、Pathクラスを使えば、OSレベルのシェルコマンドを実行する必要なく、手軽に使い捨てのファイルを作成できるのでお勧めだ。
以下に使用例を示す(実行結果は省略)。
Path('xxx.txt').touch() # カレントディレクトリにxxx.txtファイルを作成
パスが表しているのがファイルかどうかはis_fileメソッドで、ディレクトリかどうかはis_dirメソッドで調べられる。これはis_fileメソッドはos.path.isfile関数に、is_dirメソッドはos.path.isdir関数に対応するものだ。Path.is_fileメソッドは、それがファイルであればTrueを、そうでなければFalseを返す。Path.is_dirメソッドも同様に、それがディレクトリであればTrueを、そうでなければFalseを返す。
以下に例を示す。
btxt = Path('b.txt')
print('b.txt is file?', btxt.is_file())
print('b.txt is dir?', btxt.is_dir())
dxxx = Path('xxx')
print('xxx is file?', dxxx.is_file())
print('xxx is dir?', dxxx.is_dir())
これは上で作成したb.txtファイルとxxxディレクトリに対して、is_fileメソッドとis_dirメソッドを呼び出して、その結果を表示するものだ。実行結果は次のようになる。
b.txtファイルではPath.is_fileメソッドがTrueを、Path.is_dirメソッドがFalseを返している。同様に、xxxディレクトリについてはPath.is_fileメソッドがFalseを、Path.is_dirメソッドがTrueを返している。
また、先ほど紹介したdiriterメソッドと組み合わせることで次のようなことも可能だ。
file_list = [item.name for item in Path('.').iterdir() if item.is_file()]
dir_list = [item.name for item in Path('.').iterdir() if item.is_dir()]
print('files:', file_list)
print('dirs:', dir_list)
このコードではカレントディレクトリに存在するものをiterdirメソッドで列挙し、それをリスト内包表記を使って、リスト化しているが、最後に「if item.is_file()」「if item.is_dir()」のように条件を指定することで、その戻り値がTrueとなるものだけを選択するようにしている。
実行結果を以下に示す。
最後に、Pathクラスのインスタンスを使って、直接ファイルを読み書きする方法を見てみよう。open関数を使って、ファイルをオープンして、ファイルを読み込んで、クローズして……という煩雑な処理を必要とすることなく、簡便にファイルの内容を読み書きできる。ただし、書き込み時には既存のファイルは上書きされてしまう。また、読み込みでも読み込むデータの量などは指定できない。細かな制御を行いたければ、きちんとファイルを扱う必要があることは覚えておこう。
ここではPath.write_textメソッドを使って、テキストファイルに何かを書き込んで、それをPath.read_textメソッドで読み込んでみよう。以下に基本構文を示す(詳細な構文はPythonのドキュメント「Path.write_text()」「Path.read_text()」を参照のこと)。
Path.write_text(data)
Path.read_text()
Path.write_textメソッドは、そのパスが表すファイルをテキストモードでオープンして、dataを書き込んで、ファイルをクローズする。パスが既存のファイルを表している場合、そのファイルが上書きされる。
Path.read_textメソッドは、そのパスが表すファイルの内容を文字列にデコードして読み込み、ファイルをクローズする。
| パラメーター | 説明 |
|---|---|
| data | 書き込むデータ |
| Path.write_textメソッドの使用例 | |
以下に例を示す。
btxt.write_text('hello from Path.write_text method')
print(btxt.read_text())
以下に実行結果を示す。
手軽にファイルの内容を読み書きするのに便利に使えるだろう。
今回はpathlibモジュールが提供するPathクラスを利用した、ファイル/ディレクトリの操作について見た。実際にはより多くの機能をpathlibモジュールは提供しているので、興味のある方はPythonのドキュメント「pathlib --- オブジェクト指向のファイルシステムパス」を参照されたい。
Copyright© Digital Advantage Corp. All Rights Reserved.