接下來這兩天來講講 Linux 中的 Wildcard(萬用字元),在 Linux 裡面如果想要把目前資料夾下 .png
結尾的檔案都刪掉,或是要列出所有 a
開頭的檔案,不知道各位會怎麼做呢?
Linux 環境中的 Shell 大部分都會支援 Wildcard,其中比較常用的有 *
跟 ?
,分別代表 多個字元 跟 單一字元
*
代表的是任意多個字元,也可以把它理解為 任意字串
在下圖中原本有很多個 .png
檔,但經過 rm *.png
後就全部不見,這邊 *.png
代表的就是任意字串開頭、.png
結尾的檔案名稱
如果想列出 m
開頭、go
結尾的檔案,也可以用同樣的方法下 ls m*go
,這樣就會找到 mango
、mongo
跟 main.go
當然 *
也可以用來代表資料夾名稱,譬如說 ls */*.go
就可以列出所有子資料夾中 .go
結尾的檔案
?
代表的是任意一個字元,沒錯他就只能代表 一個字元,譬如說 ls m??go
就可以列出 mango
跟 mongo
,但沒辦法列出 main.go
?
也可以跟 *
搭配使用,譬如說列出所有 副檔名是兩個字 的檔案 ls *.??
,會列出所有的 .go
跟 .js
檔案
指令中之所以可以用 *
跟 ?
其實是 Shell 的功勞,當使用者下指令 ls *.go
時,Shell 看到 *.go
就會搜尋目前資料夾下符合 pattern 的檔案名稱,然後把指令 展開 成下面這一長串
ls alias.go alias_test.go color.go main.go parseArgs_test.go
所以你輸入 ls *.go
跟輸入上面那一長串的效果是一模一樣的,都會把 .go
結尾的檔案列出來
expandPattern
今天我們要實作 Wildcard 功能中最核心的一部分: 搜尋符合 pattern 的檔案
這邊我要寫一個 expandPattern
,你只要給他一個 pattern 譬如說 m??go
,他就會 搜尋目前資料夾內的檔案,然後把 pattern 展開 變成 "mango mongo"
字串
filepath.Glob(pattern string) []string
不知道大家聽到要自己實作「搜尋目前資料夾內的檔案,然後把 pattern 展開」有沒有嚇到,因為這其實不太容易,真的要做也是可以,但要做得好可能得花個兩三天就是了XD
但其實 Go 已經有提供 Glob(pattern string)
,你給他一個 pattern 他就會回傳符合條件的 string array 給你,譬如說給他 m??go
他就會給你 ["mango", "mongo"]
,是不是超方便的呢
strings.Join(strs []string, sep string)
Join
可以用來把 []string
組合成字串,譬如說 Join(["s1", "s2", "s3"], " ")
意思是把三個字串連起來、中間加入空白,就會變成 "s1 s2 s3"
func expandPattern(pattern string) string {
// 把 pattern 丟進去 Glob 讓他幫我找到符合的檔案名稱
// filenames = ["mango", "mongo"]
filenames, _ := filepath.Glob(pattern)
// 再把檔名連起來
// ["mango", "mongo"] -> "mango mongo"
return strings.Join(filenames, " ")
}
今天介紹了 Linux 中的 Wildcard 功能還有原理,如果你原本就熟悉這些指令的話應該完全沒有難度;實作部分也還算簡單,因為最難的搜尋部分 Go 幫我們做掉了,害我自從開始寫 Go 之後就越來越懶,什麼都不用自己做XD
一樣有問題的話歡迎在下方提問,沒問題的話明天就要用今天寫好的 expandPattern
來完成 Wildcard 的功能