HOWTO · Python

在 Python 中列出目錄和子目錄中的所有檔案

本教程演示如何在 Python 中列出目錄和子目錄中的所有檔案。

本頁內容

若要取得起始目錄下所有檔案的路徑,請使用 Python 的 os.walk()。它會走訪目錄樹,並逐次提供目前的目錄、其子目錄名稱及檔案名稱。將目前目錄與各檔案名稱組合,即可建立路徑。以下範例列出的是檔案,而非目錄項目。

執行此範例:

本節中的程式碼以及顯示的標籤或輸出仍為英文。

from pathlib import Path
import os
import tempfile

with tempfile.TemporaryDirectory() as temporary_directory:
    root = Path(temporary_directory) / "project"
    (root / "reports").mkdir(parents=True)
    for relative_path in ("notes", "data.csv", "reports/summary.txt", "reports/2025.csv"):
        (root / relative_path).write_text("sample", encoding="utf-8")

    for current, directories, filenames in os.walk(root):
        directories.sort()
        for filename in sorted(filenames):
            print(Path(current, filename).relative_to(root))
data.csv
notes
reports/2025.csv
reports/summary.txt

這個臨時範例會建立自己的目錄樹,其中包含一個沒有副檔名的檔案,並列印相對於起始目錄的路徑。若要建立完整路徑,可改用 Path(current, filename) 或 os.path.join(current, filename)。儲存結果時,相對路徑很方便;將檔案傳給其他程式碼時,則可使用絕對路徑。路徑分隔符號會依目前的作業系統選用。

使用 os.walk() 遞迴列出檔案

上方的迴圈使用 os.walk() 作為簡單遞迴列檔的預設方法。每次迭代時,第一個值是目前目錄的路徑,第二個值是可變動的子目錄名稱清單,第三個值則是目前目錄中的檔案名稱。只走訪第三個值,就能避免把目錄列入結果。若需要固定的走訪順序,可將子目錄名稱排序。預設情況下,走訪時發生的錯誤會遭忽略;若應用程式需要回報錯誤,請提供 onerror。

使用 os.listdir() 自訂遞迴走訪

os.listdir(path) 會傳回單一目錄中各項目的名稱,不會走訪子目錄。若要自訂走訪方式,請維護一個待檢查路徑的堆疊。對每個路徑,走訪 os.listdir(path) 傳回的名稱,使用 os.path.join() 將各名稱與其父目錄組合;檔案加入結果,目錄則加入堆疊。請使用 os.path.isfile() 和 os.path.isdir() 檢查項目類型。這種方式可自行控制走訪順序與篩選條件,但遞迴邏輯和檔案系統錯誤都必須由程式碼處理。

使用 os.scandir() 檢查目錄項目

os.scandir(path) 會逐一產生單一目錄中的 DirEntry 物件。這些物件的 is_file() 和 is_dir() 方法,方便你判斷要收集哪些項目,以及是否要走訪子目錄。可沿用上方所述的堆疊走訪方式,並以 with os.scandir(path) as entries: 開啟各目錄,確保迭代器能妥善關閉。若項目類型或中繼資料會影響你的判斷,這種方式就很實用。

使用 glob.glob() 依模式比對檔案

若要依模式選取項目,glob.glob(os.path.join(root, "**", "*"), recursive=True) 會比對任何深度的名稱,包括沒有副檔名的名稱。啟用 recursive=True 時,** 元件會涵蓋各層目錄。Glob 結果可能包含目錄;若只需要檔案,請使用 os.path.isfile(path) 篩選。若要選取特定檔案類型,可使用較窄的模式,例如 "**/*.csv";"*.*" 則會排除名稱中沒有句點的項目。

使用 pathlib.Path 遞迴列出檔案

pathlib.Path(root).rglob("*") 會遞迴產生根目錄下各層的路徑。使用 path.is_file() 篩選結果,即可排除目錄。傳回的物件是 Path 實例,因此可使用 relative_to(root) 和 name 等方法,不必手動組合字串。若某個 API 要求字串路徑,請使用 str(path)。

根據任務選擇方法

若要使用清楚的預設方法,並分開取得檔案名稱與子目錄名稱,請選擇 os.walk()。若走訪時需要檢查項目類型或中繼資料,請選擇 os.scandir()。需要依模式比對時,請使用 glob.glob();若程式以路徑物件為主,則可使用 pathlib.Path.rglob()。若需要自訂走訪規則,且願意自行實作遞迴邏輯,請選擇 os.listdir()。這些方法傳回的是路徑或名稱,不是檔案內容;若要讀取或處理檔案,請另外開啟路徑。若起始目錄不存在或無法讀取,請依使用的 API 及應用程式所需行為處理檔案系統錯誤。