Pythonのglobで条件を満たすパスの一覧を再帰的に取得する方法
Pythonのglobモジュールは、ワイルドカードパターンを使用してファイルやディレクトリを検索する強力なツールです。本記事では、再帰的な検索を含むglobの様々な使用方法を詳しく解説します。
globの基本的な使い方
基本的なワイルドカード検索
import glob
# 現在のディレクトリの.txtファイルを取得
txt_files = glob.glob("*.txt")
print(txt_files) # ['file1.txt', 'file2.txt']
# 特定のパターンにマッチするファイルを取得
python_files = glob.glob("test_*.py")
print(python_files) # ['test_main.py', 'test_utils.py']
複数文字のワイルドカード
import glob
# 任意の文字列にマッチ
files = glob.glob("data_*.csv")
print(files) # ['data_2023.csv', 'data_backup.csv']
# 単一文字のワイルドカード
files = glob.glob("file?.txt")
print(files) # ['file1.txt', 'file2.txt'] (fileA.txtは除外)
再帰的な検索
基本的な再帰検索
import glob
# サブディレクトリを含むすべての.pyファイルを取得
py_files = glob.glob("**/*.py", recursive=True)
print(py_files)
# ['main.py', 'src/utils.py', 'tests/test_main.py']
特定の階層での検索
import glob
# 2階層下までの.txtファイルを取得
txt_files = glob.glob("*/*/*.txt")
print(txt_files) # ['docs/api/readme.txt']
# 任意の階層の特定ディレクトリ内のファイル
config_files = glob.glob("**/config/*.ini", recursive=True)
print(config_files)
pathlibを使用したモダンなglob
pathlibのglob機能
from pathlib import Path
path = Path(".")
# 基本的な検索
txt_files = list(path.glob("*.txt"))
print([f.name for f in txt_files])
# 再帰的な検索
py_files = list(path.glob("**/*.py"))
print([str(f) for f in py_files])
rglob()を使用した再帰検索
from pathlib import Path
path = Path(".")
# rglob()は自動的に再帰検索を行う
py_files = list(path.rglob("*.py"))
print([str(f) for f in py_files])
# 特定パターンの再帰検索
test_files = list(path.rglob("test_*.py"))
print([f.name for f in test_files])
高度な検索パターン
複数の拡張子を同時に検索
import glob
from pathlib import Path
# globでの方法
extensions = ['*.txt', '*.md', '*.rst']
doc_files = []
for ext in extensions:
doc_files.extend(glob.glob(f"**/{ext}", recursive=True))
print(doc_files)
# pathlibでの方法
path = Path(".")
doc_files = []
for ext in ['.txt', '.md', '.rst']:
doc_files.extend(path.rglob(f"*{ext}"))
print([str(f) for f in doc_files])
特定のディレクトリを除外した検索
from pathlib import Path
def find_files_excluding_dirs(root_path, pattern, exclude_dirs):
root = Path(root_path)
results = []
for file in root.rglob(pattern):
# 除外ディレクトリが親パスに含まれていないかチェック
if not any(excluded in file.parts for excluded in exclude_dirs):
results.append(file)
return results
# 使用例:__pycache__とnode_modulesを除外
py_files = find_files_excluding_dirs(".", "*.py", ["__pycache__", "node_modules"])
print([str(f) for f in py_files])
実践的な使用例
ログファイルの日付別検索
import glob
from datetime import datetime
# 特定日付のログファイルを検索
date_pattern = "2024-01"
log_files = glob.glob(f"**/logs/*{date_pattern}*.log", recursive=True)
print(log_files)
# 今月のログファイルを検索
current_month = datetime.now().strftime("%Y-%m")
current_logs = glob.glob(f"**/logs/*{current_month}*.log", recursive=True)
print(current_logs)
ファイルサイズによるフィルタリング
from pathlib import Path
def find_large_files(root_path, pattern, min_size_mb):
root = Path(root_path)
large_files = []
for file in root.rglob(pattern):
if file.is_file():
size_mb = file.stat().st_size / (1024 * 1024)
if size_mb >= min_size_mb:
large_files.append({
'path': str(file),
'size_mb': round(size_mb, 2)
})
return large_files
# 10MB以上の画像ファイルを検索
large_images = find_large_files(".", "*.{jpg,png,gif}", 10)
for img in large_images:
print(f"{img['path']}: {img['size_mb']}MB")
最新の更新日時でソート
from pathlib import Path
import glob
def get_recent_files(pattern, count=5):
files = glob.glob(pattern, recursive=True)
file_info = []
for file_path in files:
path = Path(file_path)
if path.is_file():
mtime = path.stat().st_mtime
file_info.append({
'path': str(path),
'mtime': mtime
})
# 更新時間でソート(新しい順)
file_info.sort(key=lambda x: x['mtime'], reverse=True)
return file_info[:count]
# 最新の5つの.pyファイルを取得
recent_py_files = get_recent_files("**/*.py")
for file_info in recent_py_files:
print(file_info['path'])
パフォーマンスを考慮した検索
大量ファイルの効率的な検索
from pathlib import Path
import os
def efficient_search(root_path, extensions, max_depth=None):
"""効率的なファイル検索"""
root = Path(root_path)
results = []
def search_directory(directory, current_depth=0):
if max_depth and current_depth >= max_depth:
return
try:
for item in directory.iterdir():
if item.is_file() and item.suffix.lower() in extensions:
results.append(item)
elif item.is_dir() and not item.name.startswith('.'):
search_directory(item, current_depth + 1)
except PermissionError:
# 権限のないディレクトリをスキップ
pass
search_directory(root)
return results
# 使用例
image_files = efficient_search(".", ['.jpg', '.png', '.gif'], max_depth=3)
print(f"見つかった画像ファイル: {len(image_files)}件")
条件付き検索の組み合わせ
from pathlib import Path
import fnmatch
def complex_search(root_path, include_patterns, exclude_patterns=None):
"""複雑な条件での検索"""
root = Path(root_path)
results = []
exclude_patterns = exclude_patterns or []
for file in root.rglob("*"):
if not file.is_file():
continue
# インクルードパターンのチェック
included = any(fnmatch.fnmatch(file.name, pattern)
for pattern in include_patterns)
# エクスクルードパターンのチェック
excluded = any(fnmatch.fnmatch(str(file), pattern)
for pattern in exclude_patterns)
if included and not excluded:
results.append(file)
return results
# 使用例:Pythonファイルを検索、テストファイルとキャッシュを除外
py_files = complex_search(
".",
include_patterns=["*.py"],
exclude_patterns=["*/test_*", "*/__pycache__/*", "*/.*/*"]
)
print([str(f) for f in py_files])
まとめ
globモジュールとpathlibは、条件を満たすファイルを効率的に検索するための強力なツールです。単純なワイルドカード検索から複雑な条件での再帰検索まで、様々な用途に対応できます。大量のファイルを扱う場合は、パフォーマンスを考慮した実装を心がけ、用途に応じて適切な方法を選択することが重要です。
■プロンプトだけでオリジナルアプリを開発・公開してみた!!
■AI時代の第一歩!「AI駆動開発コース」はじめました!
テックジム東京本校で先行開始。
■テックジム東京本校
「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。
<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。
<月1開催>放送作家による映像ディレクター養成講座
<オンライン無料>ゼロから始めるPython爆速講座


