首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

Python 目錄遍歷完整指南:os.walk、os.listdir、pathlib 實戰比較

     編輯:更多程式設計知識

目錄遍歷是檔案處理、批次作業、資料收集的基礎操作。Python 提供多種方式:os.listdir(單層)、os.walk(遞迴、最常用)、glob(模式匹配)、pathlib(現代物件導向)。本文系統比較各方法特性、參數、效能與實戰範例。

核心方法比較總覽

方法模組遞迴回傳型別適用場景
os.listdiros否(單層)list[str]只需當前目錄檔案列表
os.walkos是(預設深度優先)generator of (root, dirs, files)完整目錄樹遍歷、批次處理
glob.globglob支援 ** 遞迴list[str]模式匹配檔案(如 *.py)
pathlib.Path.rglobpathlib是generator[Path]現代 OO 風格、路徑操作豐富
os.scandiros否iterator[DirEntry]高效能單層掃描(Python 3.5+)

os.walk 深度解析(最推薦通用方法)

基本語法


import os

for root, dirs, files in os.walk(top, topdown=True, onerror=None, followlinks=False):
    # root: 當前目錄路徑 (str)
    # dirs: 子目錄名稱列表 (list[str])
    # files: 檔案名稱列表 (list[str])
    pass

參數說明

  • top:起始目錄路徑
  • topdown:True(預設)= 先處理父目錄再遞迴子目錄;False = 後序遍歷(先處理最深層)
  • onerror:錯誤處理函式,接收 OSError 例外
  • followlinks:True 追蹤符號連結(預設 False,避免無限迴圈)

基本範例:列出所有檔案完整路徑


import os

for root, dirs, files in os.walk('/path/to/dir'):
    for file in files:
        full_path = os.path.join(root, file)
        print(full_path)

topdown 參數影響遍歷順序


# topdown=True (預設):預序遍歷
# 輸出順序:/a → /a/b → /a/b/c → /a/d

# topdown=False:後序遍歷
# 輸出順序:/a/b/c → /a/b → /a/d → /a
# 適用:刪除目錄樹(必須先刪子目錄再刪父目錄)

即時修改 dirs 列表控制遞迴(強大技巧)


import os

for root, dirs, files in os.walk('/path/to/dir', topdown=True):
    # 過濾不想進入的目錄(如 .git, __pycache__, venv)
    dirs[:] = [d for d in dirs if not d.startswith('.') and d not in ('__pycache__', 'venv')]
    
    for file in files:
        if file.endswith('.py'):
            print(os.path.join(root, file))

關鍵:必須用 dirs[:] = ... 就地修改列表內容,重新指派 dirs = ... 無效。

os.listdir + 遞迴函式(教學用、彈性高)


import os

def list_all_files(start_path, result=None):
    if result is None:
        result = []
    for name in os.listdir(start_path):
        full = os.path.join(start_path, name)
        if os.path.isdir(full):
            list_all_files(full, result)
        else:
            result.append(full)
    return result

files = list_all_files('/path/to/dir')

pathlib.Path 現代物件導向寫法(Python 3.4+ 推薦)


from pathlib import Path

root = Path('/path/to/dir')

# 遞迴遍歷所有檔案
for file_path in root.rglob('*'):
    if file_path.is_file():
        print(file_path)           # Path 物件
        print(file_path.name)      # 檔名
        print(file_path.suffix)    # 副檔名
        print(file_path.stat().st_size)  # 檔案大小

# 模式匹配
for py_file in root.rglob('*.py'):
    print(py_file)

# 非遞迴:iterdir()
for item in root.iterdir():
    print(item.name, 'DIR' if item.is_dir() else 'FILE')

glob 模式匹配(簡單檔案搜尋)


import glob

# 非遞迴
glob.glob('/path/to/dir/*.py')

# 遞迴 (Python 3.5+)
glob.glob('/path/to/dir/**/*.py', recursive=True)

# 含路徑分隔符的模式
glob.glob('/path/to/dir/*/*.txt')

os.scandir 高效能單層掃描(Python 3.5+)


import os

with os.scandir('/path/to/dir') as entries:
    for entry in entries:
        # entry 是 DirEntry 物件,擁有快取的 stat 資訊
        print(entry.name, entry.is_dir(), entry.is_file(), entry.stat().st_size)

優勢:避免重複 os.path.join + os.stat 系統呼叫,大目錄下顯著加速。

實戰常見需求與範例

1. 統計檔案數量與總大小


import os

total_files = 0
total_size = 0
for root, dirs, files in os.walk('/path'):
    for f in files:
        fp = os.path.join(root, f)
        total_files += 1
        total_size += os.path.getsize(fp)
print(f"Files: {total_files}, Size: {total_size/1024/1024:.2f} MB")

2. 尋找大檔案(>100MB)


import os

large_files = []
for root, dirs, files in os.walk('/path'):
    for f in files:
        fp = os.path.join(root, f)
        size = os.path.getsize(fp)
        if size > 100 * 1024 * 1024:
            large_files.append((fp, size))
for fp, size in sorted(large_files, key=lambda x: -x[1]):
    print(f"{size/1024/1024:.1f} MB  {fp}")

3. 批次重命名(修正副檔名)


import os

for root, dirs, files in os.walk('/path'):
    for f in files:
        if f.endswith('.jpeg'):
            old = os.path.join(root, f)
            new = os.path.join(root, f[:-5] + '.jpg')
            os.rename(old, new)
            print(f"Renamed: {old} -> {new}")

4. 複製目錄結構(只建目錄不複製檔案)


import os

src = '/source'
dst = '/target'
for root, dirs, files in os.walk(src):
    rel = os.path.relpath(root, src)
    target_dir = os.path.join(dst, rel) if rel != '.' else dst
    os.makedirs(target_dir, exist_ok=True)

效能比較與選擇建議

場景推薦方法理由
完整目錄樹遍歷、批次處理os.walk標準庫、生成器記憶體效率、支援 topdown 控制
現代專案、路徑操作多pathlib.Path.rglobOO 設計、Path 物件功能豐富、程式碼可讀性高
單純模式匹配搜尋glob.glob語法簡潔、支援 ** 遞迴
超大目錄、效能敏感os.scandir + 手動遞迴避免重複 stat 系統呼叫、最快
單層列表os.listdir / os.scandir簡單直接

常見陷阱


# 陷阱 1:os.walk 預設不跟隨符號連結
# 解決:followlinks=True(小心無限迴圈)

# 陷阱 2:修改 dirs 列表時用 dirs = [...] 而非 dirs[:] = [...]
# 錯誤:
dirs = [d for d in dirs if ...]  # 無效!
# 正確:
dirs[:] = [d for d in dirs if ...]  # 就地修改,影響遞迴

# 陷阱 3:路徑拼接用字串 + 而非 os.path.join
# 錯誤:root + '/' + file (Windows 失敗)
# 正確:os.path.join(root, file) 或 Path(root) / file

# 陷阱 4:遍歷時刪除檔案/目錄導致錯誤
# 解決:先收集路徑列表,遍歷結束後再刪除

總結

Python 目錄遍歷首選 os.walk(標準、高效、可控制遞迴),現代專案推薦 pathlib.Path.rglob(物件導向、功能豐富)。掌握 topdown 控制順序、dirs[:] 過濾目錄、os.path.join 跨平台路徑、os.scandir 高效能掃描等核心技巧,能高效完成檔案搜尋、批次處理、統計分析等實務任務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved