linux 萬用字元 glob 完全指南
在 Linux 的世界裡,檔案管理是日常工作的核心。許多初學者常誤以為萬用字元(Wildcard)僅是簡單的 * 符號,但實際上,Linux shell 透過一項名為 Globbing 的機制,提供了極其強大的檔案匹配能力。理解 Globbing 不僅能讓你更精確地操控檔案,更能大幅提升使用 find、rm、cp 等指令時的效率與安全性。本文將深入解析 Glob 的運作原理、進階用法與常見陷阱。
Globbing 的運作原理
當你在終端機輸入包含萬用字元的指令時,例如 ls *.txt,shell 並不會直接將 *.txt 傳遞給 ls 指令。相反地,shell 會先掃描當前目錄,尋找所有符合 *.txt 模式的檔案名稱,並將匹配到的檔案列表展開(Expand)後再傳遞給指令。
舉例來說,若當前目錄下有 a.txt、b.txt 和 c.log,執行以下指令:
ls *.txt
shell 實際執行的動作等同於:
ls a.txt b.txt
這種預處理機制意味著,萬用字元的匹配範圍僅限於 當前目錄,不會遞迴進入子目錄。若需遞迴搜尋,必須搭配 find 指令或使用 shopt -s globstar 啟用雙星號功能。
核心萬用字元符號解析
Linux shell 支援三種主要的萬用字元符號,它們各自有不同的匹配規則:
1. 星號 *:匹配零或多個字元
這是使用頻率最高的符號。它會匹配任何字元(包含空字串),但不會匹配以 . 開頭的隱藏檔案。
# 建立測試檔案
touch file1.txt file2.log .hidden.txt
# 列出所有副檔名為 txt 的檔案(不含隱藏檔)
ls *.txt
# 輸出: file1.txt file2.log (假設 file2 也是 txt 則列出)
# 注意: .hidden.txt 不會被列出
# 列出所有 txt 檔案,包含隱藏檔
ls .* *.txt
# 輸出: . .hidden.txt .. file1.txt file2.txt
2. 問號 ?:匹配單一字元
與 * 不同,? 僅匹配 一個 任意字元。這在需要精確控制檔案名稱長度時非常有用。
# 建立測試檔案
touch a1 b2 c3 ab12
# 匹配第一個字元任意,第二個字元為數字,第三個字元任意的檔案
ls ?[0-9]?
# 輸出: a1 b2 c3 (假設檔案名符合此模式)
# 僅匹配恰好三個字元的檔案
ls ???
3. 方括號 []:字元集合與範圍
方括號允許你指定一組特定的字元。若字元在開頭加上 ^ 或 !,則表示「排除」這些字元。
# 建立測試檔案
touch apple.txt banana.txt cherry.txt dog.txt
# 僅匹配開頭為 a, b, c 的檔案
ls [abc]*.txt
# 輸出: apple.txt banana.txt cherry.txt
# 匹配開頭為 a 到 z 之間的檔案
ls [a-z]*.txt
# 排除開頭為 a 的檔案
ls [^a]*.txt
# 輸出: banana.txt cherry.txt dog.txt
進階技巧:brace expansion 與 globstar
雖然嚴格來說 Brace Expansion {} 在技術上發生在 Globbing 之前,但常與萬用字元搭配使用,是提升效率的關鍵。
Brace Expansion {}
用於生成字串列表,特別適合建立多個檔案或進行批量操作。
# 建立多個目錄
mkdir -p {backup,logs,cache}/daily
# 將檔案複製到多個位置
cp data.csv backup/{daily,weekly}/
Globstar **
預設情況下,* 不匹配路徑分隔符 /。若要遞迴匹配子目錄中的檔案,需在 Bash 4.0+ 中啟用 globstar。
# 啟用 globstar
shopt -s globstar
# 匹配所有子目錄下的 .log 檔案
ls **/*.log
常見問題與注意事項
1. 萬用字元與引號的衝突
這是新手最容易踩的坑。萬用字元展開發生在指令執行之前。若你將萬用字元放在雙引號 "*" 或單引號 '*.txt' 中,shell 會將其視為普通字串,而不會進行展開。
# 錯誤示範:ls 會嘗試尋找名為 "*.txt" 的檔案,而非展開匹配
ls "*.txt"
# 正確示範:不加引號,讓 shell 先展開
ls *.txt
2. 空結果處理
若沒有檔案符合萬用字元模式,shell 預設會將模式原樣傳遞給指令,這可能導致錯誤。
# 若當前目錄沒有 .xyz 檔案,ls 會嘗試開啟名為 "*.xyz" 的檔案
ls *.xyz
# 輸出: ls: cannot access '*.xyz': No such file or directory
# 解決方案:使用 shopt -s nullglob,讓空模式展開為空字串
shopt -s nullglob
files=(*.xyz)
if [ ${#files[@]} -gt 0 ]; then
echo "Found files: ${files[@]}"
else
echo "No files found"
fi
小結
Globbing 是 Linux shell 中強大且隱形的檔案匹配引擎。透過熟練運用 *、?、[] 以及進階的 ** 和 {},你可以大幅簡化檔案管理指令。記住,萬用字元是在 shell 層級展開,而非指令內部處理,這意味著引號的使用與空結果處理是確保指令安全執行的關鍵。掌握這些細節,你的 Linux 操作將更加精準與高效。