「os.path.join と os.path.basename と os.listdir と…どれがどれだっけ?」

Pythonでファイルを扱っていると、こんなふうに関数名を調べ直すこと、ありますよね😅

そんなときに覚えておきたいのが、標準ライブラリの pathlib(パスリブ)です。パスを「文字列」ではなく「Pathオブジェクト」として扱うことで、ファイル・フォルダ操作をぐっと読みやすく書けるようになります。

この記事はPythonの基本文法がわかる初心者〜初級者向けです。インストール不要(Python 3.4以降に標準搭載)なので、手元のPythonですぐ試せます。一緒に見ていきましょう!

pathlibとは?os.pathとの違い

folders files organized
folders files organized / Photo by Jakub Zerdzicki via Pexels

イメージとしては、「パスに便利なメソッドが最初から付いている」のがpathlibです。

os.pathでは「文字列のパス」をいろいろな関数に渡して処理します。pathlibでは、Pathオブジェクト自身が .name や .exists() といった属性・メソッドを持っているので、「パス.やりたいこと」の形で書けます。

よく使う操作を対応表にまとめるとこんな感じです。

やりたいこと os / os.path pathlib
パスを結合 os.path.join(a, b) Path(a) / b
ファイル名を取得 os.path.basename(p) p.name
親フォルダを取得 os.path.dirname(p) p.parent
拡張子を取得 os.path.splitext(p)[1] p.suffix
存在チェック os.path.exists(p) p.exists()
フォルダ作成 os.makedirs(p, exist_ok=True) p.mkdir(parents=True, exist_ok=True)
フォルダの中身一覧 os.listdir(p) p.iterdir()

右の列のほうが「何をしているか」が読み取りやすいですよね。

基本:パスを作って、情報を取り出す

まずは一番よく使う基本操作です。/ 演算子でパスをつなげられるのがpathlibの大きな特徴です。

from pathlib import Path

# 「/」演算子でパスをつなげられる
p = Path("reports") / "2026" / "sales_09.csv"

print("パス全体:", p)
print("ファイル名:", p.name)      # 拡張子つきの名前
print("名前だけ:", p.stem)        # 拡張子を除いた名前
print("拡張子:", p.suffix)        # .csv
print("親フォルダ:", p.parent)    # reports/2026
print("存在する?:", p.exists())  # まだ作っていないので False

# 拡張子だけ差し替えたパスを作る(元の p は変わらない)
print("拡張子変更:", p.with_suffix(".xlsx"))
基本操作の実行結果
基本操作の実行結果

ポイントをまとめるとこんな感じです。

  • / でつなぐだけで、OSに合った区切り文字(Windowsなら \、Mac・Linuxなら /)になる
  • name(拡張子つき)と stem(拡張子なし)の違いは要チェック
  • with_suffix() は新しいPathを返すだけで、実際のファイル名は変わらない

実行結果の区切り文字が \ になっているのはWindowsで実行したためです。Macで実行すると reports/2026/sales_09.csv のように表示されます。

実践:ダウンロードフォルダを拡張子ごとに自動整理する

基本がわかったところで、ちょっと実用的なスクリプトを作ってみましょう。フォルダ内のファイルを拡張子ごとのサブフォルダに振り分ける整理ツールです。

いきなり本物のダウンロードフォルダで試すと危ないので、練習用のフォルダとダミーファイルを自動で作るところから始めています。

from pathlib import Path

# 練習用のフォルダとファイルを用意する
downloads = Path("sample_downloads")
downloads.mkdir(exist_ok=True)
for name in ["memo.txt", "photo.jpg", "report.pdf", "data.csv", "icon.png", "todo.txt"]:
    (downloads / name).write_text("dummy", encoding="utf-8")

# 拡張子ごとにサブフォルダへ振り分ける
for f in sorted(downloads.iterdir()):
    if not f.is_file():
        continue  # フォルダはスキップ
    ext = f.suffix.lstrip(".").lower() or "no_ext"
    dest_dir = downloads / ext
    dest_dir.mkdir(exist_ok=True)       # 既にあってもエラーにしない
    f.rename(dest_dir / f.name)         # ファイルを移動
    print(f"{f.name} → {ext}/")

# 振り分け後の .txt を再帰的に数える
txt_files = list(downloads.rglob("*.txt"))
print("txtファイル数:", len(txt_files))
フォルダ整理の実行結果
フォルダ整理の実行結果

ここが重要です👇

  • iterdir() でフォルダの中身を1つずつ取り出せる(sorted() で一覧を先に確定させてから移動しているので、途中で中身が変わっても安全)
  • is_file() でフォルダを除外している(2回目以降の実行で作成済みのサブフォルダを動かさないため)
  • mkdir(exist_ok=True) ならフォルダが既にあってもエラーにならない
  • rename() でファイルを移動できる
  • rglob("*.txt") はサブフォルダの中まで探してくれる(今いるフォルダだけなら glob())

本番のフォルダで使うときは、downloads = Path.home() / "Downloads" のように書き換えればOKです。ただし移動先に同じ名前のファイルがあると、Windowsではエラーに、Mac・Linuxでは上書きになります。大事なファイルがあるフォルダで使う前に、必ずコピーしたフォルダで動作を確認しておきましょう。

ファイルの読み書きもPathだけで完結

ちょっとしたテキストの読み書きなら、open() を使わずにPathのメソッドだけで済ませられます。

from pathlib import Path

log = Path("output") / "log.txt"
log.parent.mkdir(parents=True, exist_ok=True)   # 途中のフォルダもまとめて作成

log.write_text("1行目\n2行目\n", encoding="utf-8")  # 書き込み(上書き)
text = log.read_text(encoding="utf-8")             # 読み込み
print(text.splitlines())

print("絶対パス?:", log.resolve().is_absolute())
  • parents=True を付けると、途中のフォルダもまとめて作成してくれる
  • write_text() は上書き。追記したいときは従来どおり open("a") を使う
  • encoding="utf-8" は必ず指定しておく(Windowsでは省略すると文字化けの原因になることがある)

大きなファイルを1行ずつ処理したいときは、with log.open(encoding="utf-8") as fp: のように Pathの open() メソッドも使えます。with 文との組み合わせ方は、組み込みの open() とまったく同じです。

初心者がつまずきやすいポイント

① Pathを文字列として使いたいとき

最近のライブラリはほとんどPathをそのまま受け取れますが、文字列と連結したいときは str(p) で変換します。"保存先: " + p はエラーになるので、f文字列(f"保存先: {p}")を使うのがおすすめです。

② 相対パスの基準は「実行したフォルダ」

Path("data.csv") は、スクリプトの場所ではなくターミナルで実行したときのカレントフォルダが基準です。スクリプトと同じフォルダを基準にしたいなら Path(__file__).parent / "data.csv" と書きましょう。

まとめ

pathlibを使うと、「パス.やりたいこと」の形で直感的にファイル操作が書けるようになります。今回のポイントはこの3つです。

  • パスの結合は / 演算子
  • 名前・拡張子・親フォルダは name / suffix / parent
  • フォルダ作成は mkdir(parents=True, exist_ok=True) が定番

既存のスクリプトの os.path を1か所ずつpathlibに置き換えてみるだけでも、「むずかしそう」が「できそう」に変わるはずです。ぜひ手を動かして試してみてください🚀

📚 関連商品・おすすめ書籍

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

もしも

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

初心者に定番のPython入門書

Amazonで見る
Python Web開発実践入門 ―― FastAPIによるWebAPI開発と非同期処理

もしも

Python Web開発実践入門 ―― FastAPIによるWebAPI開発と非同期処理

FastAPIでWebAPI開発を実践的に学ぶ

Amazonで見る
ESP32&Arduino 電子工作 プログラミング入門

もしも

ESP32&Arduino 電子工作 プログラミング入門

ESP32とArduinoで電子工作を学ぶ入門書

Amazonで見る

※本記事にはアフィリエイトリンクが含まれます。

ABOUT ME
やまちゃん
これまで学生と社会人を合わせて5000人以上にプログラミング学習を指導。 ゼロからイチをわかりやすく解説する専門家として活動しており、本業ではArduinoを用いたIoT開発とロボットプログラミングが専門。 Pythonを用いたアプリ開発、ウェブアプリケーションの開発で業務の効率化をサポートしています。