iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 17
2

前言

接下來這兩天來講講 Linux 中的 Wildcard(萬用字元),在 Linux 裡面如果想要把目前資料夾下 .png 結尾的檔案都刪掉,或是要列出所有 a 開頭的檔案,不知道各位會怎麼做呢?

Wildcard

Linux 環境中的 Shell 大部分都會支援 Wildcard,其中比較常用的有 *?,分別代表 多個字元單一字元

任意多個字元(*)

* 代表的是任意多個字元,也可以把它理解為 任意字串

在下圖中原本有很多個 .png 檔,但經過 rm *.png 後就全部不見,這邊 *.png 代表的就是任意字串開頭、.png 結尾的檔案名稱

如果想列出 m 開頭、go 結尾的檔案,也可以用同樣的方法下 ls m*go,這樣就會找到 mangomongomain.go

當然 * 也可以用來代表資料夾名稱,譬如說 ls */*.go 就可以列出所有子資料夾中 .go 結尾的檔案

任意一個字元(?)

? 代表的是任意一個字元,沒錯他就只能代表 一個字元,譬如說 ls m??go 就可以列出 mangomongo,但沒辦法列出 main.go

? 也可以跟 * 搭配使用,譬如說列出所有 副檔名是兩個字 的檔案 ls *.??,會列出所有的 .go.js 檔案

Wildcard 原理

指令中之所以可以用 *? 其實是 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" 字串

會用到的 function

  • 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, " ")
}

小結

View commit on Github

今天介紹了 Linux 中的 Wildcard 功能還有原理,如果你原本就熟悉這些指令的話應該完全沒有難度;實作部分也還算簡單,因為最難的搜尋部分 Go 幫我們做掉了,害我自從開始寫 Go 之後就越來越懶,什麼都不用自己做XD

一樣有問題的話歡迎在下方提問,沒問題的話明天就要用今天寫好的 expandPattern 來完成 Wildcard 的功能

延伸閱讀


上一篇
Day16-which 指令在哪兒
下一篇
Day18-wildcard 萬用字元(二)
系列文
Gosh!原來用 Go 寫一個 Unix Shell 這麼簡單30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言