在檔案處理、資料清洗或自動化腳本中,經常需要遞迴或非遞迴地掃描目錄,取得符合特定條件的檔案路徑列表。Python 內建的 os 模組與 glob 模組提供了多種靈活的方式。本文將介紹三種常見做法,並提供可直接使用的工具函數。
os.listdir + 過濾(最基礎)import os
def get_files_basic(dir_path: str, extensions: tuple = ()) -> list:
"""回傳目錄下所有檔案完整路徑,可選擇性依副檔名過濾"""
files = []
for fname in os.listdir(dir_path):
full = os.path.join(dir_path, fname)
if os.path.isfile(full):
if not extensions or fname.lower().endswith(extensions):
files.append(full)
return sorted(files)
glob.glob(支援萬用字元)import glob
def get_files_glob(dir_path: str, pattern: str = '*') -> list:
"""使用 glob 模式匹配,例如 '*.txt'、'**/*.py'(遞迴)"""
search_path = os.path.join(dir_path, pattern)
# recursive=True 需 Python 3.5+
return sorted(glob.glob(search_path, recursive=True))
os.walk 遞迴掃描(功能最完整)import os
import fnmatch
def get_files_walk(root_dir: str, patterns: list = None) -> list:
"""
遞迴掃描 root_dir,支援多重 fnmatch 模式(如 ['*.txt', '*.md'])。
若 patterns 為 None,則回傳所有檔案。
"""
matched = []
for dirpath, _, filenames in os.walk(root_dir):
for fname in filenames:
if patterns is None or any(fnmatch.fnmatch(fname, pat) for pat in patterns):
matched.append(os.path.join(dirpath, fname))
return sorted(matched)
結合上述邏輯,寫一個既支援遞迴、又支援多模式、又能選擇是否回傳相對路徑的函數:
import os
import fnmatch
from typing import List, Optional, Tuple
def list_files(
root: str,
patterns: Optional[List[str]] = None,
recursive: bool = True,
absolute: bool = True
) -> List[str]:
"""
取得檔案路徑列表。
Args:
root: 起始目錄。
patterns: fnmatch 模式列表,如 ['*.txt', '*.csv'];None 表不過濾。
recursive: 是否遞迴子目錄。
absolute: True 回傳絕對路徑,False 回傳相對 root 的相對路徑。
Returns:
排序後的檔案路徑列表。
"""
result = []
if recursive:
walker = os.walk(root)
else:
# 非遞迴:只處理第一層
walker = [(root, [], os.listdir(root))]
for dirpath, _, filenames in walker:
for fname in filenames:
if patterns is None or any(fnmatch.fnmatch(fname, pat) for pat in patterns):
full = os.path.join(dirpath, fname)
result.append(os.path.abspath(full) if absolute else os.path.relpath(full, root))
return sorted(result)
if __name__ == '__main__':
# 1. 當前目錄下所有 .py 檔(不遞迴)
print(list_files('.', patterns=['*.py'], recursive=False))
# 2. 遞迴取得所有 .jpg、.png 圖片(絕對路徑)
imgs = list_files('/data/photos', patterns=['*.jpg', '*.png'])
print(f"共找到 {len(imgs)} 張圖片")
# 3. 取得相對路徑,方便存入資料庫或輸出報表
rel = list_files('project/src', patterns=['*.js', '*.ts'], absolute=False)
for f in rel:
print(f)
| 方法 | 適用場景 | 優點 | 缺點 |
|---|---|---|---|
| os.listdir | 單層目錄、簡單過濾 | 無額外依賴、速度快 | 需自行判斷檔案/目錄、不支援遞迴 |
| glob.glob | 需萬用字元匹配、遞迴 | 語法簡潔、支援 ** 遞迴 | 大量檔案時記憶體佔用較高 |
| os.walk | 複雜遞迴、自定義邏輯 | 控制力最強、可邊走邊處理 | 代碼較冗長 |
根據專案需求選擇合適的方式:簡單腳本用 glob 最省事;大規模掃描或需精細控制(如排除特定目錄、邊走邊上傳)則用 os.walk 封裝的工具函數最靈活。