Python pathlibでファイル一覧を取得する方法(glob・iterdir完全ガイド)

iterdir() – ディレクトリの直下ファイル一覧

基本的な使い方

from pathlib import Path

# 現在のディレクトリの内容を取得
current_dir = Path('.')
for item in current_dir.iterdir():
    print(item)

# 指定したディレクトリの内容を取得
data_dir = Path('data')
if data_dir.exists() and data_dir.is_dir():
    for item in data_dir.iterdir():
        print(item)

ファイルとディレクトリを区別して取得

from pathlib import Path

def list_directory_contents(dir_path):
    """ディレクトリの内容をファイルとフォルダに分けて表示"""
    path = Path(dir_path)
    
    if not path.is_dir():
        print('指定されたパスはディレクトリではありません')
        return
    
    files = []
    directories = []
    
    for item in path.iterdir():
        if item.is_file():
            files.append(item.name)
        elif item.is_dir():
            directories.append(item.name)
    
    print('ディレクトリ:', directories)
    print('ファイル:', files)

# 使用例
list_directory_contents('.')

glob() – パターンマッチングでファイル検索

基本的なワイルドカード検索

from pathlib import Path

# 現在のディレクトリからPythonファイルを検索
current_dir = Path('.')
python_files = list(current_dir.glob('*.py'))
for file in python_files:
    print(file)

# テキストファイルを検索
text_files = list(current_dir.glob('*.txt'))
print(f'テキストファイル数: {len(text_files)}')

再帰的検索(rglob)

from pathlib import Path

# 全てのサブディレクトリからPythonファイルを検索
root_dir = Path('.')
all_python_files = list(root_dir.rglob('*.py'))
print(f'全Pythonファイル数: {len(all_python_files)}')

# 特定の名前のファイルを再帰的に検索
config_files = list(root_dir.rglob('config.json'))
for config in config_files:
    print(config)

高度なパターンマッチング

from pathlib import Path

base_dir = Path('.')

# 複数の拡張子を検索
for pattern in ['*.py', '*.txt', '*.json']:
    files = list(base_dir.glob(pattern))
    print(f'{pattern}: {len(files)}件')

# 文字数指定のパターン
three_char_files = list(base_dir.glob('???.txt'))
print('3文字のtxtファイル:', three_char_files)

# 文字範囲指定
numbered_files = list(base_dir.glob('file[0-9].txt'))
print('file0.txt〜file9.txtのファイル:', numbered_files)

実用的な使用例

ファイルタイプ別の統計情報

from pathlib import Path
from collections import defaultdict

def analyze_directory(dir_path):
    """ディレクトリ内のファイルタイプ別統計"""
    path = Path(dir_path)
    stats = defaultdict(list)
    
    # 再帰的に全ファイルを検索
    for file_path in path.rglob('*'):
        if file_path.is_file():
            extension = file_path.suffix.lower()
            if not extension:
                extension = '(拡張子なし)'
            stats[extension].append(file_path)
    
    # 結果を表示
    for ext, files in sorted(stats.items()):
        total_size = sum(f.stat().st_size for f in files)
        print(f'{ext}: {len(files)}件, {total_size:,}バイト')

# 使用例
analyze_directory('.')

最近更新されたファイルの検索

from pathlib import Path
from datetime import datetime, timedelta

def find_recent_files(dir_path, days=7):
    """指定日数以内に更新されたファイルを検索"""
    path = Path(dir_path)
    cutoff_time = datetime.now().timestamp() - (days * 24 * 60 * 60)
    recent_files = []
    
    for file_path in path.rglob('*'):
        if file_path.is_file() and file_path.stat().st_mtime > cutoff_time:
            recent_files.append(file_path)
    
    return sorted(recent_files, key=lambda x: x.stat().st_mtime, reverse=True)

# 使用例
recent = find_recent_files('.', days=3)
for file in recent[:10]:  # 最新10件
    mod_time = datetime.fromtimestamp(file.stat().st_mtime)
    print(f'{file.name}: {mod_time.strftime("%Y-%m-%d %H:%M")}')

大きなファイルの検索

from pathlib import Path

def find_large_files(dir_path, min_size_mb=10):
    """指定サイズ以上のファイルを検索"""
    path = Path(dir_path)
    min_size_bytes = min_size_mb * 1024 * 1024
    large_files = []
    
    for file_path in path.rglob('*'):
        if file_path.is_file():
            size = file_path.stat().st_size
            if size >= min_size_bytes:
                large_files.append((file_path, size))
    
    # サイズでソート
    large_files.sort(key=lambda x: x[1], reverse=True)
    return large_files

# 使用例
large_files = find_large_files('.', min_size_mb=5)
for file_path, size in large_files[:5]:  # 上位5件
    size_mb = size / (1024 * 1024)
    print(f'{file_path.name}: {size_mb:.1f}MB')

重複ファイルの検索

from pathlib import Path
import hashlib
from collections import defaultdict

def find_duplicate_files(dir_path):
    """重複ファイルを検索"""
    path = Path(dir_path)
    hash_to_files = defaultdict(list)
    
    for file_path in path.rglob('*'):
        if file_path.is_file():
            # ファイルのハッシュ値を計算
            hash_md5 = hashlib.md5()
            try:
                with file_path.open('rb') as f:
                    for chunk in iter(lambda: f.read(4096), b""):
                        hash_md5.update(chunk)
                file_hash = hash_md5.hexdigest()
                hash_to_files[file_hash].append(file_path)
            except (PermissionError, OSError):
                continue
    
    # 重複ファイルのみ抽出
    duplicates = {k: v for k, v in hash_to_files.items() if len(v) > 1}
    return duplicates

# 使用例
duplicates = find_duplicate_files('.')
for hash_value, files in duplicates.items():
    print(f'重複グループ (ハッシュ: {hash_value[:8]}...):')
    for file in files:
        print(f'  {file}')

条件付きファイル検索

複数条件での絞り込み

from pathlib import Path

def find_files_by_criteria(dir_path, extension=None, min_size=None, max_size=None):
    """複数条件でファイルを検索"""
    path = Path(dir_path)
    results = []
    
    pattern = f'*.{extension}' if extension else '*'
    
    for file_path in path.rglob(pattern):
        if not file_path.is_file():
            continue
        
        # サイズ条件をチェック
        file_size = file_path.stat().st_size
        if min_size and file_size < min_size:
            continue
        if max_size and file_size > max_size:
            continue
        
        results.append(file_path)
    
    return results

# 使用例
# 1KB以上10KB以下のPythonファイル
py_files = find_files_by_criteria('.', extension='py', 
                                min_size=1024, max_size=10240)
for file in py_files:
    print(file)

除外パターンでの検索

from pathlib import Path

def find_files_excluding(dir_path, exclude_patterns=None):
    """特定パターンを除外してファイルを検索"""
    path = Path(dir_path)
    exclude_patterns = exclude_patterns or []
    results = []
    
    for file_path in path.rglob('*'):
        if not file_path.is_file():
            continue
        
        # 除外パターンをチェック
        should_exclude = False
        for pattern in exclude_patterns:
            if file_path.match(pattern):
                should_exclude = True
                break
        
        if not should_exclude:
            results.append(file_path)
    
    return results

# 使用例
# __pycache__や.gitディレクトリを除外
files = find_files_excluding('.', exclude_patterns=[
    '*/__pycache__/*', 
    '*/.git/*', 
    '*.pyc'
])
print(f'除外後のファイル数: {len(files)}')

パフォーマンス最適化

大量ファイル処理の最適化

from pathlib import Path
import os

def fast_file_count(dir_path, extension=None):
    """高速なファイル数カウント"""
    path = Path(dir_path)
    count = 0
    
    try:
        # os.scandirを使用してより高速に処理
        with os.scandir(path) as entries:
            for entry in entries:
                if entry.is_file():
                    if extension is None:
                        count += 1
                    elif entry.name.endswith(f'.{extension}'):
                        count += 1
    except (PermissionError, FileNotFoundError):
        return 0
    
    return count

# 使用例
py_count = fast_file_count('.', 'py')
print(f'Pythonファイル数: {py_count}')

エラーハンドリング

安全なディレクトリ検索

from pathlib import Path

def safe_directory_scan(dir_path):
    """エラーハンドリング付きディレクトリスキャン"""
    path = Path(dir_path)
    
    if not path.exists():
        print(f'パスが存在しません: {path}')
        return []
    
    if not path.is_dir():
        print(f'ディレクトリではありません: {path}')
        return []
    
    files = []
    try:
        for item in path.iterdir():
            try:
                if item.is_file():
                    files.append(item)
            except (PermissionError, OSError) as e:
                print(f'アクセスエラー {item}: {e}')
                continue
    except PermissionError:
        print(f'ディレクトリへのアクセス権限がありません: {path}')
    
    return files

# 使用例
files = safe_directory_scan('/protected/directory')
print(f'アクセス可能なファイル数: {len(files)}')

まとめ

pathlibのglob()rglob()iterdir()を使うことで、柔軟で強力なファイル検索が可能になります。従来のosモジュールと比べて、より読みやすく直感的なコードが書けるのが特徴です。大量ファイルを扱う場合は、適切なエラーハンドリングとパフォーマンス最適化を心がけましょう。

「らくらくPython塾」が切り開く「呪文コーディング」とは?

■プロンプトだけでオリジナルアプリを開発・公開してみた!!

■AI時代の第一歩!「AI駆動開発コース」はじめました!

テックジム東京本校で先行開始。

■テックジム東京本校

「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。

<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。

<月1開催>放送作家による映像ディレクター養成講座

<オンライン無料>ゼロから始めるPython爆速講座