pathlibとは、ファイルやフォルダのパスを文字列ではなく「Pathオブジェクト」として扱う、Python標準ライブラリのモジュールです。 Path("data") / "orders.csv" のように / でパスをつなぎ、p.suffix で拡張子、p.read_text() で中身を読むなど、パス操作とファイル操作を1つのオブジェクトで書けます。

この記事は 「やりたいこと→コード→実行結果」の逆引き形式で70例をまとめました。すべて実際のフォルダを作って Python 3.13.7(コピー・移動の新メソッドは 3.14.7)で実行した出力を載せています。さらに、同じコードを 3.11/3.12/3.13/3.14 で動かして比べた「バージョンごとの違い」、os.path との対応表、つまずきやすいポイント(+ で結合できない、文字コード)も紹介します。コードはすべてテキストなので、そのままコピーして使えます。

pathlib逆引き早見表

まずはこの表から探してください。 番号は本文のコード内コメントに対応しています。p = Path("/tmp/pathlib-demo/data/orders.csv") を例にしています。

やりたいこと コード 結果の例
パスをつなぐ base / "data" / "orders.csv" /tmp/pathlib-demo/data/orders.csv
ファイル名 p.name orders.csv
拡張子なしの名前 p.stem orders
拡張子 p.suffix .csv
親フォルダ p.parent /tmp/pathlib-demo/data
拡張子を変える p.with_suffix(".json") .../orders.json
名前だけ変える p.with_stem("orders_2026") .../orders_2026.csv
存在確認 p.exists() True
ファイルか・フォルダか p.is_file() / p.is_dir() True / False
フォルダ作成(途中も) d.mkdir(parents=True, exist_ok=True) ―
テキストを読む p.read_text(encoding="utf-8") 文字列
テキストを書く p.write_text(s, encoding="utf-8") 書いた文字数
直下の一覧 d.iterdir() Pathのイテレータ
パターンで探す d.glob("*.csv") 〃
サブフォルダも探す d.rglob("*.csv") 〃
フォルダを巡回 d.walk()(3.12+) (dirpath, dirnames, filenames)
コピー p.copy(dst)(3.14+)/ shutil.copy2(p, dst) コピー先のPath
名前変更 p.rename(new) 新しいPath
移動(上書きあり) p.replace(new) / p.move(new)(3.14+) 新しいPath
ファイル削除 p.unlink(missing_ok=True) ―
中身ごと削除 shutil.rmtree(d) ―
サイズ p.stat().st_size 37
更新日時 datetime.fromtimestamp(p.stat().st_mtime) datetime
相対パス p.relative_to(base) data/orders.csv
.. 付きの相対パス p.relative_to(other, walk_up=True)(3.12+) ../data/orders.csv
絶対パス Path("x").resolve() 正規化された絶対パス
カレント・ホーム Path.cwd() / Path.home() /root など
スクリプトの場所 Path(__file__).resolve().parent ―
Windowsパスを解析 PureWindowsPath(r"C:\a\b.txt") ―

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Python pathlibの使い方|ファイル操作逆引き70例と実行結果」

準備:サンプルフォルダを作る

以降のコードは、次のスクリプトで作ったフォルダで実行しています。 自分の環境でも同じ結果を確かめられます。

# setup_demo.py(サンプル用のフォルダとファイルを作る。何度実行してもよい)
from pathlib import Path

base = Path("/tmp/pathlib-demo")
files = {
    "data/orders.csv": "id,item,qty\n1,ノート,3\n2,ペン,5\n",
    "data/members.csv": "id,name\n1,佐藤\n",
    "data/report.txt": "在庫レポート\n",
    "data/archive/2026-08.csv": "id,item,qty\n",
    "docs/readme.md": "# README\n",
    "docs/memo.TXT": "メモ\n",
    "src/app.py": "print('hello')\n",
    "src/utils/helper.py": "",
    ".env": "DEBUG=1\n",
}
for rel, text in files.items():
    p = base / rel
    p.parent.mkdir(parents=True, exist_ok=True)
    p.write_text(text, encoding="utf-8")
print("created:", base)

このほか、65 のスクリプトを scripts/tool.py として置いた状態で実行しています(36・41 の一覧に含まれます)。

実行環境は Linux(Python 3.13.7)です。Windowsでは区切り文字が \ で表示されます。

パスを作る・つなぐ(1〜5)

from pathlib import Path

base = Path("/tmp/pathlib-demo")
p = base / "data" / "orders.csv"          # 1. / で結合
print(p)
print(base.joinpath("data", "orders.csv"))  # 2. joinpath で結合
print(Path("data", "orders.csv"))           # 3. 複数の要素から作る
print(base / "/etc/hosts")                  # 4. 絶対パスを結合すると置き換わる
print(repr(p))
print(str(p), type(str(p)))                 # 5. 文字列に変換
/tmp/pathlib-demo/data/orders.csv
/tmp/pathlib-demo/data/orders.csv
data/orders.csv
/etc/hosts
PosixPath('/tmp/pathlib-demo/data/orders.csv')
/tmp/pathlib-demo/data/orders.csv <class 'str'>

/ の右側が / で始まる絶対パスだと、左側は捨てられて右側だけになります。 ユーザー入力などをつなぐときは、先頭の / に気をつけます。OSに合った区切り文字は pathlib が自動で使うので、"data/" + "orders.csv" のように自分で区切りを書く必要はありません。

名前・拡張子・親フォルダを取り出す(6〜14)

from pathlib import Path

p = Path("/tmp/pathlib-demo/data/archive/2026-08.csv")
print("name    :", p.name)          # 6. ファイル名
print("stem    :", p.stem)          # 7. 拡張子なしの名前
print("suffix  :", p.suffix)        # 8. 拡張子
print("suffixes:", Path("backup.tar.gz").suffixes)  # 9. 複数の拡張子
print("parent  :", p.parent)        # 10. 親フォルダ
print("parents1:", p.parents[1])    # 11. 2つ上のフォルダ
print("parts   :", p.parts)         # 12. 要素に分解
print("anchor  :", p.anchor)        # 13. ルート部分
print("parent.name:", p.parent.name)  # 14. 親フォルダの名前だけ
name    : 2026-08.csv
stem    : 2026-08
suffix  : .csv
suffixes: ['.tar', '.gz']
parent  : /tmp/pathlib-demo/data/archive
parents1: /tmp/pathlib-demo/data
parts   : ('/', 'tmp', 'pathlib-demo', 'data', 'archive', '2026-08.csv')
anchor  : /
parent.name: archive

suffix はピリオド付き(.csv)で返ります。 比較するときは p.suffix == ".csv"、大文字小文字を無視するなら p.suffix.lower() == ".csv" と書きます。

拡張子や名前を変えたパスを作る(15〜19)

from pathlib import Path

p = Path("data/orders.csv")
print(p.with_suffix(".json"))      # 15. 拡張子を変える
print(p.with_suffix(""))           # 16. 拡張子を外す
print(p.with_stem("orders_2026"))  # 17. 拡張子はそのまま名前だけ変える(3.9+)
print(p.with_name("members.csv"))  # 18. ファイル名ごと変える
print(p.with_stem(p.stem + "_bak"))  # 19. 名前の後ろに付け足す
print(Path("backup.tar.gz").with_suffix(".zip"))  # 最後の拡張子だけ変わる
data/orders.json
data/orders
data/orders_2026.csv
data/members.csv
data/orders_bak.csv
backup.tar.zip

with_〜 は新しいPathを返すだけで、実際のファイル名は変わりません。 ファイルの名前を変えるには、後述の rename() と組み合わせます(例:p.rename(p.with_suffix(".bak")))。

存在確認とファイル・フォルダの判定(20〜23)

from pathlib import Path

base = Path("/tmp/pathlib-demo")
print((base / "data/orders.csv").exists())   # 20. 存在確認
print((base / "data/nothing.csv").exists())
print((base / "data").is_dir())              # 21. フォルダか
print((base / "data/orders.csv").is_file())  # 22. ファイルか
print((base / "data").is_file())
print(Path("orders.csv").is_absolute(), base.is_absolute())  # 23. 絶対パスか
True
False
True
True
False
False True

存在しないパスの is_file()・is_dir() は False を返すので、「あって、かつファイルか」は is_file() だけで確かめられます。

フォルダ・空ファイルを作る(24〜25)

from pathlib import Path

base = Path("/tmp/pathlib-demo")
out = base / "output" / "2026" / "09"
out.mkdir(parents=True, exist_ok=True)   # 24. 途中のフォルダもまとめて作る
print(out.is_dir())
out.mkdir(parents=True, exist_ok=True)   # 2回目もエラーにならない

try:
    (base / "output").mkdir()            # exist_ok なし
except FileExistsError as e:
    print("FileExistsError:", e)

try:
    (base / "x" / "y").mkdir()           # parents なし
except FileNotFoundError as e:
    print("FileNotFoundError:", e)

log = base / "output" / "app.log"
log.touch()                               # 25. 空ファイルを作る
print(log.exists(), log.stat().st_size)
True
FileExistsError: [Errno 17] File exists: '/tmp/pathlib-demo/output'
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/pathlib-demo/x/y'
True 0
引数 省略時(False) True のとき
parents 親がないと FileNotFoundError 途中のフォルダもまとめて作る(mkdir -p 相当)
exist_ok すでにあると FileExistsError すでにあってもエラーにしない

「なければ作る」は mkdir(parents=True, exist_ok=True) の1行が定番です。ファイルを書く直前に p.parent.mkdir(parents=True, exist_ok=True) と書くと、保存先フォルダの準備も1行で済みます。

テキスト・バイナリを読み書きする(26〜32)

from pathlib import Path

base = Path("/tmp/pathlib-demo")
p = base / "output" / "note.txt"
n = p.write_text("備品リスト\nノート\nペン\n", encoding="utf-8")  # 26. 書き込み
print("written chars:", n)
text = p.read_text(encoding="utf-8")        # 27. 読み込み
print(repr(text))
print(text.splitlines())                    # 28. 行のリストにする

with p.open("a", encoding="utf-8") as f:    # 29. 追記
    f.write("消しゴム\n")

with p.open(encoding="utf-8") as f:         # 30. 1行ずつ読む
    for i, line in enumerate(f, 1):
        print(i, line.rstrip("\n"))

b = base / "output" / "data.bin"
b.write_bytes(bytes([0, 1, 2, 255]))        # 31. バイナリ書き込み
print(b.read_bytes())                        # 32. バイナリ読み込み
written chars: 13
'備品リスト\nノート\nペン\n'
['備品リスト', 'ノート', 'ペン']
1 備品リスト
2 ノート
3 ペン
4 消しゴム
b'\x00\x01\x02\xff'
  • write_text() はファイルを上書きし、戻り値は書いた文字数です(バイト数ではありません)。
  • 追記は open("a") を使います。write_text() には追記モードがありません。
  • 大きなファイルは open() で1行ずつ処理するとメモリを節約できます。
  • encoding は必ず指定します。省略するとOSの既定の文字コードになり、Windowsでは UTF-8 以外になることがあります(後述)。

ファイル一覧を取得・検索する(33〜40)

from pathlib import Path

base = Path("/tmp/pathlib-demo")
print(sorted(p.name for p in (base / "data").iterdir()))       # 33. 直下の一覧
print(sorted(p.name for p in (base / "data").iterdir() if p.is_file()))  # 34. ファイルだけ
print(sorted(p.name for p in (base / "data").glob("*.csv")))   # 35. 拡張子で絞る
print(sorted(str(p.relative_to(base)) for p in base.rglob("*.csv")))    # 36. サブフォルダも含めて
print(sorted(str(p.relative_to(base)) for p in base.glob("**/*.py")))   # 37. ** で再帰
print(sorted(p.name for p in base.glob("*")))                  # 38. 隠しファイルも含む
print(sorted(p.name for p in (base / "docs").glob("*.txt")))
print(sorted(p.name for p in (base / "docs").glob("*.txt", case_sensitive=False)))  # 39. 大文字小文字を無視(3.12+)
print(sorted(p.name for p in (base / "data").glob("*.[ct][sx][vt]")))  # 40. [] で文字の候補
['archive', 'members.csv', 'orders.csv', 'report.txt']
['members.csv', 'orders.csv', 'report.txt']
['members.csv', 'orders.csv']
['data/archive/2026-08.csv', 'data/members.csv', 'data/orders.csv']
['scripts/tool.py', 'src/app.py', 'src/utils/helper.py']
['.env', 'data', 'docs', 'output', 'scripts', 'src']
[]
['memo.TXT']
['members.csv', 'orders.csv', 'report.txt']

iterdir()・glob() の並び順は保証されないので、順番が必要なら sorted() で並べます。 glob() はジェネレータを返すため、件数を知りたいときや2回使いたいときは list() にします。

パターン 意味 例
* 任意の文字列(/ を含まない) *.csv
? 任意の1文字 2026-0?.csv
[abc] いずれか1文字 *.[ct][sx][vt]
** 0個以上のフォルダ **/*.py
rglob("*.csv") glob("**/*.csv") と同じ ―
  • Linux・macOSの glob は大文字小文字を区別します(*.txt で memo.TXT は見つからない)。3.12以降は case_sensitive=False で無視できます。
  • * は .env のようなドットで始まるファイルにも一致しました(シェルの ls * とは違う点)。

フォルダを巡回する walk(41)

Path.walk()(3.12以降)は os.walk() のpathlib版で、フォルダごとに「パス・サブフォルダ名・ファイル名」を返します。

from pathlib import Path

base = Path("/tmp/pathlib-demo")
for dirpath, dirnames, filenames in base.walk():   # 41. walk(3.12+)
    dirnames.sort()
    dirnames[:] = [d for d in dirnames if d != "output"]  # 除外したいフォルダ
    print(dirpath.relative_to(base), sorted(filenames))
. ['.env']
data ['members.csv', 'orders.csv', 'report.txt']
data/archive ['2026-08.csv']
docs ['memo.TXT', 'readme.md']
scripts ['tool.py']
src ['app.py']
src/utils ['helper.py']

dirnames をその場で書き換えると、そのフォルダには入らなくなります(.git などを飛ばすときに使います)。

コピー・移動・名前変更・削除(42〜48)

3.13以前のコピーは shutil を使います。 pathlib の Path はそのまま shutil に渡せます。

import shutil
from pathlib import Path

base = Path("/tmp/pathlib-demo")
src = base / "data" / "orders.csv"
dst = base / "output" / "orders_copy.csv"
shutil.copy2(src, dst)                         # 42. ファイルのコピー(3.13以前)
print(dst.exists())
shutil.copytree(base / "docs", base / "output" / "docs_copy", dirs_exist_ok=True)  # 43. フォルダごとコピー
print(sorted(p.name for p in (base / "output" / "docs_copy").iterdir()))

moved = dst.rename(base / "output" / "orders_renamed.csv")   # 44. 名前変更
print(moved.name, dst.exists())
new = moved.replace(base / "output" / "2026" / "orders.csv")  # 45. 移動(上書きあり)
print(new.relative_to(base))

tmp = base / "output" / "tmp.txt"
tmp.write_text("x", encoding="utf-8")
tmp.unlink()                                   # 46. ファイル削除
tmp.unlink(missing_ok=True)                    # ないときもエラーにしない
print(tmp.exists())

empty = base / "output" / "empty"
empty.mkdir(exist_ok=True)
empty.rmdir()                                  # 47. 空フォルダの削除
shutil.rmtree(base / "output" / "docs_copy")  # 48. 中身ごとフォルダ削除
print(empty.exists(), (base / "output" / "docs_copy").exists())
True
['memo.TXT', 'readme.md']
orders_renamed.csv False
output/2026/orders.csv
False
False False
メソッド 移動先にファイルがあるとき 用途
rename() Windowsではエラー、Linux・macOSでは上書き 名前変更
replace() どのOSでも上書き 確実に置き換えたいとき
shutil.move() 別ドライブへの移動にも対応 ドライブをまたぐ移動

rename()・replace() は新しいパスを返します。 元の変数(dst)は古いパスのままなので、以降は戻り値を使います。

Python 3.14 の copy / copy_into / move / move_into(49〜52)

Python 3.14 から、Path に copy()・copy_into()・move()・move_into() が加わり、shutil なしでコピー・移動できます。 Python 3.14.7 で実行しました。

import sys
from pathlib import Path

print(sys.version.split()[0])
base = Path("/tmp/pathlib-demo")
src = base / "data" / "orders.csv"
r = src.copy(base / "output" / "orders_314.csv")          # 49. Path.copy(3.14+)
print(r)
r = src.copy_into(base / "output")                         # 50. フォルダの中へコピー(3.14+)
print(r)
r = (base / "docs").copy(base / "output" / "docs314")      # フォルダもコピーできる
print(sorted(p.name for p in r.iterdir()))
r = (base / "output" / "orders_314.csv").move(base / "output" / "2026" / "orders_314.csv")  # 51. 移動(3.14+)
print(r)
r = (base / "output" / "docs314").move_into(base / "output" / "2026")  # 52. フォルダの中へ移動(3.14+)
print(r)
3.14.7
/tmp/pathlib-demo/output/orders_314.csv
/tmp/pathlib-demo/output/orders.csv
['memo.TXT', 'readme.md']
/tmp/pathlib-demo/output/2026/orders_314.csv
/tmp/pathlib-demo/output/2026/docs314

copy() はファイルにもフォルダにも使え、戻り値はコピー先のPathです。 〜_into() は「そのフォルダの中に同じ名前で」置きます。3.13で copy() を呼ぶと AttributeError: 'PosixPath' object has no attribute 'copy' になりました。

ファイルサイズ・更新日時(53〜56)

from datetime import datetime
from pathlib import Path

p = Path("/tmp/pathlib-demo/data/orders.csv")
st = p.stat()
print("size :", st.st_size, "bytes")                           # 53. ファイルサイズ
print("mtime:", datetime.fromtimestamp(st.st_mtime).strftime("%Y-%m-%d %H:%M"))  # 54. 更新日時
latest = max(Path("/tmp/pathlib-demo/data").glob("*.csv"), key=lambda x: x.stat().st_mtime)
print("latest:", latest.name)                                  # 55. 最新のファイル
total = sum(f.stat().st_size for f in Path("/tmp/pathlib-demo").rglob("*") if f.is_file())
print("total:", total, "bytes")                                # 56. フォルダの合計サイズ
size : 37 bytes
mtime: 2026-09-29 13:04
latest: members.csv
total: 560 bytes

orders.csv は日本語を含むため、文字数(27文字)ではなく UTF-8 のバイト数(37バイト)になります。st_mtime はエポック秒なので、datetime.fromtimestamp() で日時に変換します。

相対パス・絶対パス・ホーム・スクリプトの場所(57〜65)

import os
from pathlib import Path

base = Path("/tmp/pathlib-demo")
p = base / "data" / "archive" / "2026-08.csv"
print(p.relative_to(base))                                  # 57. 相対パスにする
try:
    print(p.relative_to(base / "docs"))
except ValueError as e:
    print("ValueError:", e)
print(p.relative_to(base / "docs", walk_up=True))           # 58. .. を使った相対パス(3.12+)
print(os.path.relpath(p, base / "docs"))                     # 3.11以前はこちら
print(p.is_relative_to(base), p.is_relative_to("/etc"))     # 59. 配下かどうか

os.chdir(base / "src")
print(Path.cwd())                                            # 60. カレントフォルダ
print(Path("../data/orders.csv").absolute())                # 61. 絶対パス(.. は残る)
print(Path("../data/orders.csv").resolve())                 # 62. 正規化した絶対パス
print(Path.home())                                           # 63. ホームフォルダ
print(Path("~/work").expanduser())                           # 64. ~ を展開
data/archive/2026-08.csv
ValueError: '/tmp/pathlib-demo/data/archive/2026-08.csv' is not in the subpath of '/tmp/pathlib-demo/docs'
../data/archive/2026-08.csv
../data/archive/2026-08.csv
True False
/tmp/pathlib-demo/src
/tmp/pathlib-demo/src/../data/orders.csv
/tmp/pathlib-demo/data/orders.csv
/root
/root/work
メソッド .. の扱い シンボリックリンク 使いどころ
absolute() そのまま残す 解決しない 見た目だけ絶対パスにしたい
resolve() 取り除く 解決する 比較・保存用の正規化したパス

スクリプトと同じフォルダのファイルを読むときは、カレントフォルダではなく __file__ を基準にします。 /tmp/pathlib-demo/scripts/tool.py として保存し、別のフォルダ(/tmp)から実行しました。

# scripts/tool.py
from pathlib import Path

HERE = Path(__file__).resolve().parent        # 65. このスクリプトのフォルダ
print(HERE.name)
config = HERE / "config.toml"                 # スクリプトの隣のファイル
print(config.name, config.parent == HERE)
scripts
config.toml True

Path("config.toml") はカレントフォルダ基準なので、実行場所で結果が変わります。__file__ 基準ならどこから実行しても同じ場所を指せます。

一時フォルダを使う(66)

import tempfile
from pathlib import Path

with tempfile.TemporaryDirectory() as d:       # 66. 一時フォルダ
    tmp = Path(d)
    (tmp / "work.txt").write_text("一時データ", encoding="utf-8")
    print(tmp.parent, [p.name for p in tmp.iterdir()])
    saved = tmp
print(saved.exists())                          # with を抜けると消える
/tmp ['work.txt']
False

TemporaryDirectory() は文字列を返すので、Path(d) で包んで使います。 pytest なら tmp_path フィクスチャが最初から Path で渡されます。

Windowsのパスを扱う(67〜69)

PureWindowsPath を使うと、Linux・macOS上でもWindows形式のパスを解析できます。 ファイルにはアクセスせず、文字列としての操作だけを行うクラスです。

from pathlib import PurePosixPath, PureWindowsPath, Path

w = PureWindowsPath(r"C:\Users\taro\Documents\report.xlsx")   # 67. Windowsパスを扱う
print(w.name, w.suffix, w.drive, w.parent)
print(w.as_posix())                                           # 68. / 区切りにする
print(PureWindowsPath("C:/data") / "orders.csv")              # / で書いても \ になる
print(PureWindowsPath("DATA/Orders.CSV") == PureWindowsPath("data/orders.csv"))  # Windowsは大文字小文字を区別しない
print(PurePosixPath("DATA/Orders.CSV") == PurePosixPath("data/orders.csv"))
print(Path("/tmp/pathlib-demo/data/orders.csv").as_uri())      # 69. file:// URI
print(PureWindowsPath(r"\\server\share\file.txt").drive)       # UNCパス
report.xlsx .xlsx C: C:\Users\taro\Documents
C:/Users/taro/Documents/report.xlsx
C:\data\orders.csv
True
False
file:///tmp/pathlib-demo/data/orders.csv
\\server\share
  • Windowsのパスを文字列で書くときは r"..."(raw文字列)にします。 "C:\new" のように書くと \n が改行として解釈されます。
  • Windows上でも Path("C:/data/orders.csv") と / で書いて問題ありません。 pathlib が \ に直して扱います。

パターンに一致するか判定する(70)

from pathlib import PurePath

q = PurePath("data/archive/2026-08.csv")
print(q.match("*.csv"), q.match("data/*.csv"))          # match は右から比べる
print(q.full_match("data/**/*.csv"), q.full_match("*.csv"))  # 70. 全体で比べる(3.13+)
True False
True False

match() はパスの右端から比べ、full_match()(3.13以降)はパス全体で比べます。 ** を使った判定には full_match() を使います。

Python 3.11〜3.14 でのpathlibの違い(実行比較)

同じコードを4つのバージョンで実行した結果です。 業務で古いバージョンを使っている場合の確認に使えます。

機能 3.11.15 3.12.3 3.13.7 3.14.7
walk() AttributeError 使える 使える 使える
relative_to(..., walk_up=True) TypeError 使える 使える 使える
glob(..., case_sensitive=False) TypeError 使える 使える 使える
with_segments() AttributeError 使える 使える 使える
glob("data/**") の結果 フォルダだけ(data、data/archive) フォルダだけ ファイルも含む(6件) ファイルも含む
full_match() AttributeError AttributeError 使える 使える
Path.from_uri() AttributeError AttributeError 使える 使える
read_text(newline=...) TypeError TypeError 使える 使える
copy()・move() など AttributeError AttributeError AttributeError 使える
Path("file.").suffix '' '' '' '.'
with_suffix(".") ValueError: Invalid suffix '.' 同左 同左 a.

特に注意したいのは、3.13で ** で終わるパターンの結果が変わった点です。 3.12までは glob("data/**") がフォルダだけを返していましたが、3.13以降はファイルも返します(公式ドキュメントの「Changed in version 3.13」にも記載)。フォルダだけが欲しい場合は、if p.is_dir() で絞り込むとどのバージョンでも同じ結果になります。

os.path との対応表

os.path から移行するときの対応表です。 左の書き方は今も使えますが、pathlib にすると1つのオブジェクトで完結します。

やりたいこと os / os.path pathlib
結合 os.path.join(a, "b.csv") Path(a) / "b.csv"
ファイル名 os.path.basename(p) p.name
親フォルダ os.path.dirname(p) p.parent
拡張子で分ける os.path.splitext(p) → ('backup.tar', '.gz') p.stem、p.suffix
存在確認 os.path.exists(p) p.exists()
絶対パス os.path.abspath(p) p.absolute()(.. を消すなら p.resolve())
正規化 os.path.realpath(p) p.resolve()
相対パス os.path.relpath(p, start) p.relative_to(start, walk_up=True)(3.12+)
一覧 os.listdir(d) d.iterdir()
パターン検索 glob.glob("*.csv") d.glob("*.csv")
巡回 os.walk(d) d.walk()(3.12+)
フォルダ作成 os.makedirs(d, exist_ok=True) d.mkdir(parents=True, exist_ok=True)
ファイル削除 os.remove(p) p.unlink()
名前変更 os.rename(a, b) a.rename(b)
サイズ os.path.getsize(p) p.stat().st_size
更新日時 os.path.getmtime(p) p.stat().st_mtime
読み込み open(p, encoding=...).read() p.read_text(encoding=...)

open()・shutil・pandas.read_csv() など多くの関数は Path をそのまま受け取れます(os.PathLike に対応しているため)。str(p) への変換が必要なのは、文字列を前提とした古いライブラリや、文字列として連結したい場合だけです。

よくあるミスと直し方

実際に実行して確認したエラーと結果です。

ミス 実際の結果 直し方
base + "/data" TypeError: unsupported operand type(s) for +: 'PosixPath' and 'str' base / "data"
"demo" in str(p) で判定 途中の文字列にも一致する p.name ==、p.suffix == で比べる
cp932(Shift_JIS)のファイルを encoding="utf-8" で読む UnicodeDecodeError: 'utf-8' codec can't decode byte 0x94 in position 0: invalid start byte p.read_text(encoding="cp932") → 備品
BOM付きUTF-8(encoding="utf-8-sig" で保存)を utf-8 で読む 先頭3バイト b'\xef\xbb\xbf' が残り、.startswith("id") が False encoding="utf-8-sig" で読むと True
encoding を省略 OSの既定の文字コードで読み書きされる 常に encoding="utf-8" などを明記
with_suffix() だけ呼ぶ 新しいPathを返すだけでファイル名は変わらない p.rename(p.with_suffix(".bak"))
Path("data/") 末尾の / は消えて data になる(Path("data/") == Path("data") は True) フォルダかどうかは is_dir() で判定

よくある質問

Q. pathlib と os.path はどちらを使うべきですか? A. 新しく書くコードでは pathlib が読みやすく、結合・名前の取得・読み書きまでを1つのオブジェクトで扱えます。既存コードの os.path はそのまま動くので、触る部分から上の対応表を使って少しずつ置き換えると安全です。

Q. Path と PurePath の違いは? A. PurePath はパスを文字列として操作するだけで、ファイルにアクセスしません。Path は PurePath の機能に加えて、存在確認や読み書きなどのファイル操作ができます。普段は Path、別のOS形式のパスを解析するときは PureWindowsPath・PurePosixPath を使います。

Q. glob の結果が空になります。 A. 大文字小文字の違い(Linux・macOS)、カレントフォルダの違い、パターンの書き間違いの順に確認します。print(Path.cwd()) で基準の場所を確かめ、3.12以降なら case_sensitive=False も試せます。

まとめ

  • pathlib は / でパスをつなぎ、name・stem・suffix・parent で要素を取り出します。
  • フォルダ作成は mkdir(parents=True, exist_ok=True)、読み書きは read_text/write_text に encoding を明記します。
  • 一覧は iterdir()、検索は glob()・rglob()、巡回は walk()(3.12+)。順番が必要なら sorted() を使います。
  • 3.14 から copy()・move() が加わり、3.13以前は shutil と組み合わせます。
  • relative_to(..., walk_up=True) は 3.12+、glob("**") がファイルも返すのは 3.13+ など、バージョンによる違いに気をつけます。
  • スクリプトの隣のファイルは Path(__file__).resolve().parent を基準にするとどこから実行しても同じ場所を指せます。
  • + ではなく /、文字化けは encoding の指定で解決できます。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Python pathlibの使い方|ファイル操作逆引き70例と実行結果」

株式会社RJCでは、pathlibのような標準ライブラリを使いこなして読みやすいコードを書く工夫を、プロジェクトの中で仲間と共有しています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?