每週一個 Python 模組 | glob

yongxinz發表於2019-01-30

專欄地址:每週一個 Python 模組

使用 Unix shell 規則查詢與模式匹配的檔名。

儘管 glob API 不多,但該模組具有很強的功能。當程式需要通過名稱與模式匹配的方式查詢檔案列表時,它很有用。要建立一個檔案列表,這些檔名具有特定的副檔名,字首或中間的任何公共字串,這個時候,使用glob而不是編寫自定義程式碼來掃描目錄內容。

glob 模式規則與 re 模組使用的正規表示式不同。相反,它們遵循標準的 Unix 路徑擴充套件規則,只有少數特殊字元用於實現兩個不同的萬用字元和字元範圍。模式規則應用於檔名段(在路徑分隔符處停止/),模式中的路徑可以是相對的或絕對的,Shell 變數名和波浪號(~)不會展開。

示例資料

本節中的示例假定當前工作目錄中存在以下測試檔案。

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
複製程式碼

萬用字元

星號(*)匹配名稱段中的零個或多個字元。例如,dir/*

import glob
for name in sorted(glob.glob('dir/*')):
    print(name)
    
# output
# 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
複製程式碼

該模式匹配目錄 dir 中的每個路徑名(檔案或目錄),而不會進一步遞迴到子目錄中。返回的資料未排序,因此這裡的示例對其進行排序以便更直觀地展示結果。

要列出子目錄中的檔案,子目錄必須包含在模式中。

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))
    
# output
# Named explicitly:
#   dir/subdir/subfile.txt
# Named with wildcard:
#   dir/subdir/subfile.txt
複製程式碼

前面顯示的第一種情況明確列出了子目錄名稱,而第二種情況依賴於萬用字元來查詢目錄。

在這種情況下,結果是相同的。如果有另一個子目錄,則萬用字元將匹配兩個子目錄幷包含兩者的檔名。

單字元萬用字元

問號(?)是另一個萬用字元。它匹配名稱中該位置的任何單個字元。

import glob

for name in sorted(glob.glob('dir/file?.txt')):
    print(name)
    
# output
# dir/file*.txt
# dir/file1.txt
# dir/file2.txt
# dir/file?.txt
# dir/file[.txt
# dir/filea.txt
# dir/fileb.txt
複製程式碼

示例匹配所有以 file 開頭的檔名,具有任何型別的單個字元,然後以 .txt 結束。

字元範圍

使用字元範圍([a-z])而不是問號來匹配多個字元之一。此示例在副檔名之前查詢名稱中帶有數字的所有檔案。

import glob
for name in sorted(glob.glob('dir/*[0-9].*')):
    print(name)
    
# output
# dir/file1.txt
# dir/file2.txt
複製程式碼

字元範圍[0-9]匹配任何單個數字。範圍根據每個字母/數字的字元程式碼排序,短劃線表示連續字元的連續範圍。可以寫入相同的範圍值[0123456789]

轉義元字元

有時需要搜尋名稱中包含特殊元字元(glob用於模式匹配)的檔案。escape()函式使用特殊字元“轉義”構建合適的模式,因此它們不會被擴充套件或解釋為特殊字元。

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()
    
# output
# Searching for: 'dir/*[?].txt'
# dir/file?.txt
# 
# Searching for: 'dir/*[*].txt'
# dir/file*.txt
# 
# Searching for: 'dir/*[[].txt'
# dir/file[.txt
複製程式碼

通過構建包含單個條目的字元範圍來轉義每個特殊字元。

相關文件:

pymotw.com/3/glob/inde…

相關文章