linux 萬用字元 glob 完全指南 文章首圖

linux 萬用字元 glob 完全指南

linux 萬用字元 glob 完全指南

在 Linux 的世界裡,檔案管理是日常工作的核心。許多初學者常誤以為萬用字元(Wildcard)僅是簡單的 * 符號,但實際上,Linux shell 透過一項名為 Globbing 的機制,提供了極其強大的檔案匹配能力。理解 Globbing 不僅能讓你更精確地操控檔案,更能大幅提升使用 findrmcp 等指令時的效率與安全性。本文將深入解析 Glob 的運作原理、進階用法與常見陷阱。

Globbing 的運作原理

當你在終端機輸入包含萬用字元的指令時,例如 ls *.txt,shell 並不會直接將 *.txt 傳遞給 ls 指令。相反地,shell 會先掃描當前目錄,尋找所有符合 *.txt 模式的檔案名稱,並將匹配到的檔案列表展開(Expand)後再傳遞給指令。

舉例來說,若當前目錄下有 a.txtb.txtc.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 操作將更加精準與高效。