iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 16
2

前言

不知道大家還記不記得有一個指令叫做 which,它可以用來找某個指令在哪裡,譬如說 which ls 可以找到 ls 是放在 /bin/ls

但如果是 alias 的指令怎麼辦?在 zsh 裡面他會跟你說這個指令被 alias 成什麼,譬如說我的 gst 是被 alias 成 git status

這也是為什麼一直拖到現在才實作這個指令,因為前幾天才剛把 alias 做完

which 也是內建指令

大家想一想,which 如果想要知道 gst 被 alias 成什麼指令,那他就一定得去查 Alias Table,但因為 Alias Table 只有 Shell 才知道,其他 Process 根本不知道 Alias Table 裡面的對應關係,所以 which 也必須以 Shell 內建指令的方式實作

如果在 zsh 中用 which 來查 which 在哪裡,也會看到他是個內建指令

which 流程

which 的輸出結果大致上可以分成這三種:

1. 在 Alias Table 裡面

如果指令有在 Alias Table 裡面,譬如說 gst,那就輸出 gst: aliased to git status

2. 在 PATH 裡面

如果指令沒有在 Alias Table 裡面,譬如說 ls,那就到 PATH 裡面找找看 ls 在哪裡,並輸出 ls: /bin/ls

3. 沒有這個指令

如果連 PATH 裡面都找不到指令,譬如說 gggg,那就是沒有這個指令,輸出 gggg NOT FOUND

實作

會用到的 function

  • exec.LookPath(file string)

    LookPath 會在 PATH 裡面尋找檔案,譬如說 LookPath("ls") 就會得到 /bin/ls,如果找不到的話則會回傳錯誤

實作 lookCommand

我們要根據上面的 which 流程實作一個 lookCommand,他會分別到 Alias Table 跟 PATH 裡面找指令並且輸出

func lookCommand(cmd string) {
    // 先到 Alias Table 裡面找找看指令(gst)
    value := aliasTable[cmd]
    
    // 如果找到的話就輸出 gst: aliased to git status
    // 沒找到的話就繼續往下走
    if value != "" {
        fmt.Printf("%s: aliased to %s\n", cmd, value)
        return
    }

    // 到 PATH 裡面找找看指令(ls)
    value, err := exec.LookPath(cmd)
    
    // 找到的話就輸出 ls: /bin/ls
    // 沒找到的話就繼續往下走
    if err == nil {
        fmt.Printf("%s: %s\n", cmd, value)
        return
    }

    // Alias Table 跟 PATH 都找不到這個指令(gggg)
    // 直接輸出 gggg NOT FOUND
    fmt.Printf("%s NOT FOUND\n", cmd)
}

接著到 execInput 裡面加上這段

func executeInput(input string) error {
    // ...
    
    // 如果使用者下的指令是 which 開頭
    // 譬如說 which gst ls gggg
    if args[0] == "which" {
        // 那就把 gst, ls, gggg 依序傳到 lookCommand 裡面
        // 讓他跑上面的 which 流程
        for _, cmd := range args[1:] {
            lookCommand(cmd)
        }
        return nil
    }
    
    // ...
}

Demo

先把 gst 設定成 git status,再看看 gstlsgggg 三個指令分別在哪裡

小結

View commit on Github

今天自己用之前寫好的 Alias Table 跟 Go 提供的 LookPath 實作了 which 指令,有沒有覺得很有趣呢?如果有什麼問題歡迎在下方留言,沒問題的話明後兩天要來講好用的 Wildcard(萬用字元) 囉


上一篇
Day15-alias 指令別名(四)
下一篇
Day17-wildcard 萬用字元(一)
系列文
Gosh!原來用 Go 寫一個 Unix Shell 這麼簡單30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言