Python | ファイル・OS 操作:glob

Python Python
スポンサーリンク

概要(glob は「パターンに合うファイルを一気に列挙」する標準手段)

glob は、ワイルドカードを使って「条件に合うファイルやフォルダ」をまとめて取得する仕組みです。拡張子が .csv のファイルだけ、report_で始まるファイルだけ、といった抽出が1行で書けます。モジュールの glob.glob と、pathlib の Path.glob/Path.rglob の2系統があり、どちらも同じパターンで動きますが、pathlib はパス操作(結合・分解)まで一緒に扱えるのが強みです。重要なのは「ワイルドカードの意味」「再帰検索のやり方」「取得順・安全性の扱い」を押さえることです。

基本の使い方(ここが重要)

glob.glob で文字列パスのリストを得る

import glob

# カレントディレクトリの .txt だけ
files = glob.glob("*.txt")
print(files)  # ['memo.txt', 'notes.txt'] など
Python

glob.glob は「パターンに合うパス文字列のリスト」を返します。相対パスも絶対パスも使えます。

pathlib の Path.glob でパスオブジェクトを得る

from pathlib import Path

p = Path("data")
for f in p.glob("*.csv"):
    print(f, f.name, f.stem, f.suffix)
Python

Path.glob は Path オブジェクト(OS非依存の安全な扱い)で返してくれるので、そのまま open、read_text、with_suffix などと組み合わせられます。

ワイルドカードと再帰検索(意味を正しく使い分ける)

代表的なワイルドカードの意味

    • は「0文字以上の任意の文字」
  • ? は「ちょうど1文字」
  • [] は「文字クラス」(例:file[0-9].log は file0.log~file9.log に一致)
import glob
print(glob.glob("*.py"))         # 末尾が .py
print(glob.glob("data?.csv"))    # data1.csv, dataA.csv など1文字
print(glob.glob("file[0-9].log"))
Python

** と再帰検索(サブディレクトリまで)

import glob

# すべての下位ディレクトリの .py を再帰的に
files = glob.glob("**/*.py", recursive=True)
Python

pathlib なら rglob を使うと簡潔です。

from pathlib import Path

for f in Path(".").rglob("*.py"):
    print(f)
Python

角括弧の文字クラス例(範囲・否定)

import glob
print(glob.glob("img[0-5].png"))   # 0〜5
print(glob.glob("img[!0-5].png"))  # 0〜5 以外
Python

よくある実務パターン(拡張子選別・並び・読み書き・安全性)

拡張子で選んでまとめて処理

from pathlib import Path

for csv in Path("data").glob("*.csv"):
    text = csv.read_text(encoding="utf-8")
    # ここでパース・集計などを行う
Python

日付や接頭辞での選別

from pathlib import Path

base = Path("logs/2025")
for log in base.glob("access_2025-12-??.log"):  # 12月の日付全て
    print(log)
Python

取得順序の扱い(明示的に並べる)

glob は「ファイルシステムの順序」で返すため、表示や処理の順を安定させたいならソートします。

from pathlib import Path

files = sorted(Path("images").glob("*.png"))          # 名前順
files = sorted(Path("images").glob("*.png"), key=lambda p: p.stat().st_mtime)  # 更新時刻順
Python

見つからないときの防御(空リスト・空イテレータ)

0件でも例外にはなりません。処理側で空を許容するか、明示的にチェックします。

from pathlib import Path

imgs = list(Path("images").glob("*.png"))
if not imgs:
    print("画像が見つかりません")
Python

パス操作と組み合わせる(出力先を安全に用意)

from pathlib import Path

src_dir = Path("data/raw")
out_dir = Path("data/processed")
out_dir.mkdir(parents=True, exist_ok=True)

for src in src_dir.glob("*.txt"):
    out = out_dir / (src.stem + ".out")
    out.write_text(src.read_text(encoding="utf-8").upper(), encoding="utf-8")
Python

深掘りポイント(エスケープ・隠しファイル・性能・落とし穴)

ワイルドカードを“文字そのもの”として扱いたいときのエスケープ

文字列に * や ? を「そのままの文字」として検索したい場合は、pathlib では扱いが難しいため、明示的なフィルタに切り替えます。

from pathlib import Path

files = [p for p in Path(".").iterdir() if p.name.endswith("[*].txt")]  # 例:明示フィルタ
Python

glob.escape(globモジュール)でパターンをエスケープする方法もありますが、用途に応じて選びます。

隠しファイル(ドット始まり)の扱い

単純な *.txt では .hidden.txt のようなドット始まりは含まれないことが多いです。必要ならパターンを調整します。

from pathlib import Path

visible = list(Path(".").glob("*.txt"))
hidden  = list(Path(".").glob(".*.txt"))
Python

性能の勘所(再帰・大規模ディレクトリ)

再帰(**)は探索範囲が広く、巨大なツリーでは時間がかかります。基点を絞る、より限定的なパターンにする、不要ディレクトリを除外するなどで負荷を下げます。結果をすぐ使い切るなら、list(…) にせずループで流すとメモリを節約できます。

文字列連結ではなく「結合+glob」で安全に

f文字列や“手作り”の文字列連結でパスを作ると OS差異やバグの温床になります。基点は Path で結合(/ 演算子)、検索は glob に任せる方針が安全です。

from pathlib import Path

base = Path("data") / "logs" / "2025"
for f in base.glob("*.log"):
    ...
Python

例題で身につける(定番から一歩先まで)

例題1:サブディレクトリも含めて .csv を全部読む

from pathlib import Path

total_rows = 0
for csv in Path("data").rglob("*.csv"):
    text = csv.read_text(encoding="utf-8")
    total_rows += len(text.splitlines())
print("rows:", total_rows)
Python

例題2:report_YYYYMMDD.csv の最新だけ処理

from pathlib import Path

files = sorted(Path("reports").glob("report_20*.csv"))  # 名前順に並べる
if files:
    latest = files[-1]
    print("latest:", latest)
Python

例題3:画像を拡張子ごとに拾って別フォルダへコピー

from pathlib import Path
import shutil

src = Path("images")
dst = Path("images_selected")
dst.mkdir(parents=True, exist_ok=True)

for ext in ("*.png", "*.jpg", "*.jpeg"):
    for f in src.glob(ext):
        shutil.copy2(f, dst / f.name)
Python

例題4:ログを日付で分けて一括圧縮対象を列挙

from pathlib import Path

base = Path("logs/2025/12")
targets = sorted(base.glob("access_2025-12-*.log"))
for t in targets:
    print(t)
# ここで圧縮処理などへ渡す
Python

まとめ

glob は「パターンでファイル群を一括取得する」ための標準機能で、.txt、file[0-9].log、/.py といった表現で抽出できます。文字列なら glob.glob、パス操作まで含めるなら pathlib の Path.glob/Path.rglob が扱いやすい選択です。再帰検索は ** と recursive(または rglob)、取得順は必要に応じて sorted で明示。拡張子・日付・接頭辞などの選別を正しく行い、pathlib による結合・分解・読み書きと組み合わせれば、実務の「ファイルをまとめて扱う」処理が短く安全に書けます。探索範囲の絞り込みとループでの“作らず流す”を意識し、ワイルドカードの意味を誤らないことが、安定したファイル処理の鍵です。

タイトルとURLをコピーしました