glob — 檔名規則匹配
儘管 glob API 很少,但是功能強大。在那種需要查詢系統上匹配一個模式的檔案時非常有用。當需要去建立一個有某個相同擴充套件,字首或者中間有共同字串的檔案列表時,應該考慮使用 glob 而不是自定義處理目錄內容的程式碼。
glob 模組使用的模式規則不同於 re 模組使用的正則表示式。而是使用 Unix 路徑擴充套件規則。只有少數特殊字元用去實現兩個不同的萬用字元以及特殊字元。模式規則應用於檔名的段(以路徑分隔符 / 為界)。模式中的路徑可以是相對的或者絕對的。Shell 變數名和波浪符( ~ )不會被展開。
示例資料
假設這個例子中的測試檔案是存在於當前工作目錄的。
$ python3 glob_maketestdata.py dir dir/file.txt dir/file1.txt dir/file2.txt dir/filea.txt dir/fileb.txt dir/file?.txt dir/file*.txt dir/file[.txt dir/subdir dir/subdir/subfile.txt
如果這些檔案不存在,請在執行接下來例子之前使用示例程式碼中的 glob_maketestdata.py 建立它們。
萬用字元
一個星號( * )匹配名稱片段中零個或者多個字元,例如,dir/*。
glob_asterisk.py import glob for name in sorted(glob.glob('dir/*')): print(name)
這個模式匹配 「 dir 」目錄中的每個路徑名稱(檔案或者目錄),但是不會進一步遞迴遍歷子目錄。glob 返回的資料是沒有排序的,所以例子中對它進行排序以便更清楚地研究結果。
$ python3 glob_asterisk.py dir/file*.txt dir/file.txt dir/file1.txt dir/file2.txt dir/file?.txt dir/file[.txt dir/filea.txt dir/fileb.txt dir/subdir
如果要檢視子目錄的內容,子目錄必須包含在模式中。
glob_subdir.py import glob print('Named explicitly:') for name in sorted(glob.glob('dir/subdir/*')): print(' {}'.format(name)) print('Named with wildcard:') for name in sorted(glob.glob('dir/*/*')): print(' {}'.format(name))
前面顯示的第一個例子中顯示地列出了子目錄名稱,但是第二個依賴於萬用字元查詢子目錄。
$ python3 glob_subdir.py Named explicitly: dir/subdir/subfile.txt Named with wildcard: dir/subdir/subfile.txt
在這個示例中兩種方式的結果是一樣的。但是如果這裡還有一個子目錄,萬用字元將會匹配這兩個子目錄幷包含這兩個目錄下的所有檔案。
單字元萬用字元
問好( ? )是另一個萬用字元。它匹配檔名稱中任何單個字元。
glob_question.py import glob for name in sorted(glob.glob('dir/file?.txt')): print(name)
前面的例子中匹配所有以 file 開始的檔案,緊接著是一個任何型別的字元,然後以 .txt 結束。
$ python3 glob_question.py dir/file*.txt dir/file1.txt dir/file2.txt dir/file?.txt dir/file[.txt dir/filea.txt dir/fileb.txt
字元範圍
使用字元範圍( [a-z] )而不是問號去匹配多個字元中的一個。這個例子中將會查詢到所有在副檔名之前有一個數字的檔案。
glob_charrange.py import glob for name in sorted(glob.glob('dir/*[0-9].*')): print(name)
字元範圍 [0-9] 匹配一個數字。範圍根據每個字母或者數字的字元程式碼進行排序,破折號表示字元的連續範圍。[0-9] 等同於 [0123456789] 。
$ python3 glob_charrange.py dir/file1.txt dir/file2.txt
轉義元字元
有時候可能需要去查詢一些包含 glob 模式使用的特殊字元的檔案。escape() 方法會用轉義後的特殊字元構建一個適配模式,這樣 glob 就不會將它當做特殊字元解釋處理。
glob_escape.py import glob specials = '?*[' for char in specials: pattern = 'dir/*' + glob.escape(char) + '.txt' print('Searching for: {!r}'.format(pattern)) for name in sorted(glob.glob(pattern)): print(name) print()
通過構建包含單個字元的字元範圍將每個特殊字元進行轉義。
$ python3 glob_escape.py Searching for: 'dir/*[?].txt' dir/file?.txt Searching for: 'dir/*[*].txt' dir/file*.txt Searching for: 'dir/*[[].txt' dir/file[.txt