HOWTO · Python

使用 Python 查詢檔案

我們可以使用 os 庫、glob 庫或 pathlib 庫在 Python 中查詢檔案。

本頁內容

Python 有三種實用的檔案搜尋方式:使用 os.walk() 遍歷目錄、使用 glob.glob() 比對模式,或使用 pathlib.Path.glob() 取得路徑物件。請依任務選擇合適的搜尋根目錄;掃描整台電腦可能很耗時,也可能搜尋到原本不打算納入的位置。

使用 os.walk() 尋找檔案

如果你需要自行檢查目錄樹,例如在瀏覽資料夾時套用自訂條件,可以使用 os.walk()。它會為每個目錄產生一個 tuple,內容依序是目前的目錄路徑、該目錄的直接子目錄名稱清單,以及檔名清單。第二個值不是檔案清單。若要建立搜尋結果,請將目前的目錄路徑與符合條件的檔名組合起來。如果沒有檔名符合條件,found 會保持為 None,而此範例會印出 No match。

執行以下範例。程式碼及其輸出中的文字標籤維持英文:

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

import os
from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as temporary_directory:
    root = Path(temporary_directory)
    (root / "reports").mkdir()
    (root / "reports" / "annual.txt").write_text("Ready", encoding="utf-8")

    found = None
    for directory, subdirectories, filenames in os.walk(root):
        if "annual.txt" in filenames:
            found = os.path.join(directory, "annual.txt")
            break

    print(Path(found).name if found else "No match")

此範例只會搜尋它建立的暫存目錄。在自己的程式碼中,請將 root 換成要搜尋的目錄。由於範例中的暫存根目錄是絕對路徑,找到檔案時,found 會是絕對路徑字串。如果傳入相對搜尋根目錄給 os.walk(),os.path.join(directory, "annual.txt") 會產生相對路徑。此程式只會印出符合條件的檔名 annual.txt。遍歷順序沒有保證,因此只有在任何一個符合條件的檔案都可以接受時,才在找到第一個檔案後停止。若要取得所有符合項目,請收集每個組合後的路徑,而不要立即傳回結果。os.walk() 文件 說明它產生的值與遍歷選項;目前沒有提供 zh-tw 文件目標。

使用 glob.glob() 尋找符合條件的路徑

當路徑模式能描述搜尋條件時,可以使用 glob.glob()。Glob 模式不是正規表示式:*.txt 會比對以 .txt 結尾的名稱,而 ? 會比對一個字元。預設情況下,* 不會跨越目錄分隔符號。若要搜尋巢狀目錄,請設定 recursive=True,並在模式中加入 **。此函式會傳回路徑字串清單;路徑可能是相對路徑或絕對路徑,取決於你傳入的模式。

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

import glob
from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as temporary_directory:
    root = Path(temporary_directory)
    (root / "notes").mkdir()
    (root / "notes" / "todo.txt").write_text("Call", encoding="utf-8")
    matches = glob.glob(str(root / "**" / "*.txt"), recursive=True)
    print([Path(match).name for match in matches])

此範例使用範圍明確的搜尋根目錄,並且只印出檔名部分,因此顯示的值不會受暫存目錄名稱影響。程式碼及其輸出中的文字標籤維持英文。如果你想立即取得清單,或需要以模式比對的介面,可以使用 glob.glob()。

使用 pathlib.Path.glob() 尋找路徑

Path.glob() 透過 Path 物件提供模式比對功能。它的結果是 Path 物件,可以用 / 組合路徑、透過 .name 等方法檢查,也可以直接開啟。它會以 iterator 逐一產生符合項目;若要保存結果,可以逐項走訪,或將它包在 list() 中。與 glob.glob() 不同,這裡的模式是相對於呼叫該方法的 Path;** 可以比對巢狀目錄。

程式碼及其輸出中的文字標籤維持英文:

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

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as temporary_directory:
    root = Path(temporary_directory)
    (root / "archive").mkdir()
    (root / "archive" / "summary.txt").write_text("Ready", encoding="utf-8")
    matches = sorted(root.glob("**/*.txt"))
    print([path.name for path in matches])

有多個路徑符合條件時,排序可以明確指定結果順序。具體的 Path 子類別會依作業系統而異,因此程式碼通常應使用通用的 Path 介面,而不要假設各系統顯示的值都會是 WindowsPath。如需了解支援的模式與比對行為,請參閱 Path.glob() 文件。

選擇檔案搜尋方法

如果搜尋需要在每個目錄套用自訂邏輯、取得目錄名稱,或控制遍歷過程,請選擇 os.walk()。若要簡潔地依模式搜尋並取得字串清單,請選擇 glob.glob()。若想使用相同類型的模式比對,但偏好 Path 物件及其路徑操作,請選擇 Path.glob()。這三種方法都會搜尋你提供的根目錄或起始路徑之下,不需要掃描整台電腦。請先判斷你需要一個符合項目還是所有符合項目,並盡可能縮小搜尋根目錄。若要建立可重複使用的輔助函式,也要決定找不到符合項目時呼叫端應收到什麼結果:在 os.walk() 範例中,found 會保持為 None,程式會印出 No match;而模式搜尋範例在沒有符合項目時會產生空清單。