Pythonでのファイル・ディレクトリ操作

shutil
pathlib
Python
file operation
Published

September 25, 2024

Python3でファイル・ディレクトリ操作を行う方法をまとめる。

Code
from IPython import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all'

import session_info

pathlib module

pathlibモジュールはPython 3.4から導入され、ファイルシステムのパスを操作する機能を提供する。 主要な機能を提供するPathサブクラスをimportして使用する。

pathlib --- オブジェクト指向のファイルシステムパス

ソースコード: Lib/pathlib/ このモジュールはファイルシステムのパスを表すクラスを提供していて、様々なオペレーティングシステムについての適切な意味論をそれらのクラスに持たせています。 Path クラスは 純粋パス と 具象パス からなります。 純粋パスは I/O を伴わない純粋な計算操作を提供します。 具象パスは純粋パスを継承していますが、 I/O 操作も提供しています。 Inh...

https://docs.python.org/ja/3/library/pathlib.html

from pathlib import Path
p = Path("path/to/file.txt.gz")
p
#> PosixPath('path/to/file.txt.gz')

Path("path", "to", "file.txt.gz")
#> PosixPath('path/to/file.txt.gz')

PosixPathクラスの属性

PosixPathクラスの属性にアクセスすることで、パスの特定の部分文字列を抽出することができる。

### `name`属性
# パスのbasename(パスの末尾の要素)
p.name
#> 'file.txt.gz'

### `suffix`, `suffixes`属性
# file suffix(ファイル拡張子)
p.suffix
#> '.gz'
p.suffixes
#> ['.txt', '.gz']

### `stem`属性
# パスのstem(basename - file suffix)
p.stem
#> 'file.txt'

### `parent`, `parents`属性
# parent属性でディレクトリのパス、parents属性とインデックスで一気に上位のディレクトリのパス
p.parent
#> PosixPath('path/to')
p.parents[0]
#> PosixPath('path/to')
p.parents[1]
#> PosixPath('path')

### `parts`属性
# パスを構成する要素からなるタプル
p.parts
#> ('path', 'to', 'file.txt.gz')

ファイル名の変更

with_*()メソッドでファイル名(パスの最後の要素)を変更することができる。

p.with_name("other_file.txt")
#> PosixPath('path/to/other_file.txt')

p.with_suffix(".bz2")
#> PosixPath('path/to/file.txt.bz2')

p.with_stem("another")
#> PosixPath('path/to/another.gz')

パスの探索

Path.glob()メソッドで指定したディレクトリ内のパスを返すジェネレータを得ることができる。

# forループで取り出す
for f in Path(".").glob('**/*.py'):
  print(f)
#> test/script.py
#> test/scripts/script.py

# 内包表記などでも取り扱うことができる
[f for f in Path(".").glob('**/*') if f.suffix == ".py"]
#> [PosixPath('test/script.py'), PosixPath('test/scripts/script.py')]

Pathのクラスメソッド

# ホームディレクトリ
Path.home()
#> PosixPath('/Users/t_arae')

# ワーキングディレクトリ
Path.cwd()
#> PosixPath('/Users/t_arae/blog/posts/2024/2024-09-25-python-pathlib')
p = Path("test/scripts/../scripts/../not_exist/script.py")

# absolute()は絶対パスに字句解析的に変換
p.absolute().relative_to(Path.cwd())
#> PosixPath('test/scripts/../scripts/../not_exist/script.py')

# resolve()は途中の`..`などを解消する
p.resolve().relative_to(Path.cwd())
#> PosixPath('test/not_exist/script.py')

# strict=Trueを指定すると、存在しない場合はエラーを返す
p.resolve(strict=True)
#> FileNotFoundError: [Errno 2] No such file or directory: 'test/not_exist'

shutil module

pathlibモジュールでは行いにくい一部の操作については、標準ライブラリのshutilモジュールなどを使うとよい。

shutil --- 高水準のファイル操作

ソースコード: Lib/shutil.py shutil モジュールはファイルやファイルの集まりに対する高水準の操作方法を多数提供します。特にファイルのコピーや削除のための関数が用意されています。個別のファイルに対する操作については、 os モジュールも参照してください。 ディレクトリとファイルの操作: プラットフォーム依存の効率的なコピー操作: Python 3.8 から、ファイルのコピー...

https://docs.python.org/ja/3/library/shutil.html

(ディレクトリ内の)ファイルの削除

pathlibモジュールでもファイルやディレクトリを削除するメソッドが用意されている。 しかし、やや使い勝手が悪くファイルをディレクトリごと削除したい場合などに不便である。

# ファイルの削除はunlink()メソッドで行う
Path("test/script.py").unlink()

# ファイルが存在しない場合はエラー(missing_ok引数をTrueに設定するとエラーを出さない)
Path("not_exist.txt").unlink(missing_ok=False)
#> FileNotFoundError: [Errno 2] No such file or directory: 'not_exist.txt'

# ディレクトリの削除はrmdir()メソッドで行うが、空ディレクトリ出なければ削除できない。
Path("test/").rmdir()
#> OSError: [Errno 66] Directory not empty: 'test'

フォルダごとファイルを削除するにはshutil.rmtree()関数を用いる。

import shutil
shutil.rmtree(Path("test/"))

Sessioninfo

session_info.show()
-----
IPython             8.26.0
session_info        1.0.0
-----
Python 3.12.2 (main, Feb 25 2024, 03:55:42) [Clang 17.0.6 ]
macOS-13.1-arm64-arm-64bit
-----
Session information updated at 2024-09-24 09:28