如何管理常用的 Command Line 指令?

xkcd:tar (https://imgs.xkcd.com/comics/tar.png)

有些指令很常用,但使用頻率不見得高到能讓人既起來。那麼,除了使用記事本以外,還有什麼方法能有效管理這些指令呢?

本文總結一些管理指令的經驗和訣竅,並且介紹好用的開源工具供參考。

怎麼管理常用但不見得能記起來的指令?

在初學程式的時候,我除了用 word,還會用紙本筆記紀錄程式碼和常用指令。這些紀錄就擺在我的電腦桌面和電腦桌面上,以便不時參閱。雖然有時會忘記指令放在電腦還是筆記本上,可是當時的內容不多,所以也沒特別感到困擾。大學畢業後,因為微軟的校園授權過期,我索性把所有筆記都搬遷到 Goolge Doc。由於 Google Doc 能是雲端應用程式,所以可以讓文件跨裝置讀取與保管,讓我能統一管理寫作、報告還是程式碼指令等多媒體文件。

除了文書編輯軟體,我也曾跟上筆記軟體的風潮,試著用 Evernote 和 Notion 等工具。這些軟體把筆記篇幅劃分為更小的單位,加入標籤、資料夾或是資料庫系統,提升了管理筆記的彈性;而它們通常也支持多媒體輸入,也內建全域搜尋系統,改善了許多維護與使用筆記的體驗。

筆記軟體、文書編輯軟體或紙本筆記本在紀錄筆記上各有千秋,不過據我的使用經驗,它們在管理指令上有共通的問題:查閱指令離使用指令的距離太遠了。讓我們以按鍵數量來衡量查閱與使用的距離,假設要解壓縮一份 tar.gz 檔,前述幾種方法要按上幾次鍵?打開瀏覽器/軟體/文件、啟動搜尋、鍵入關鍵字、複製指令、打開終端機、貼上指令,扣除搜索的成本,最少也要六次以上。

這聽起來很像個人 kimochi 的問題,不過如果你的職業正好是個厭世的軟體工程師,那麼想點辦法稍稍拯救一下上班的心情也是個好主意吧?屏除開發或維護的流暢性,若能確保筆記與應用場合貼近,也有助於即時更新筆記的內容。

綜合以上提及的因素,指令的良好管理方式至少具有統一管理、跨平臺存儲、貼近使用場合等特性,才能提升用戶維護與使用的流暢性。以 Command Line 指令為例,筆記最直觀的存放位置是伺服器或電腦本身,讓他們能透過 Github 備份與版本控管。由於幾乎沒有多媒體需求,使用 markdown 語法紀錄的純文本能兼具可讀性與標籤的功能性,還可在各平台讀取。此外,command line 的搜尋系統普遍比文書與筆記軟體強大,也降低了分類、標籤和重新排序的成本。

最後,還需要一些程式來銜接筆記與應用的落差,例如將搜尋到的指令直接貼到 command line,就不需要重複複製貼上。

有哪些好用的工具?

只要在 Github 主題搜尋 snippetoneliner 便能找到許多指令管理工具可以參考。以下幾款都支援指令速查與調用,而 navipet 甚至能引導用戶交互式輸入指令所需的參數。以刪除特定的 Docker image 為例,navi 可以做到用快捷鍵搜尋刪除 image 的指令,再用快捷鍵搜尋 image 的名稱,自動回填到刪除指令的參數位置。

這些工具都允許用戶依照其規範的格式增補指令,有些還內建的指令庫,彙整了像是 tldr 這樣被開源社群維護的簡明指令手冊。

  • zsh-fzf-snippet:基於 fzf 且適用於 zsh 的輕量級指令管理工具,支援指令速查與執行。核心功能只含一支腳本以及紀錄指令的設置檔。
  • easy-oneliner:同樣基於 fzf 且適用於 zsh 的輕量級指令管理工具,只是指令的記錄格式與 zsh-fzf-snippet 不同。
  • navi:基於 Python 語言的指令管理工具,彙整了 Github 著名的指令庫,除了指令速查與執行的功能外,也會交互式引導用戶輸入指令的參數。
  • pet:基於 Go 語言的指令管理工具,定位與 navi 類似,同樣具有指令速查與交互式參數輸入功能。
  • cheat.sh:彙整了 Github 著名的指令庫,只支援指令速查。有線上版本,所以不需要安裝也能使用。

如何自己寫一套指令管理工具?

由於這些工具的原理單純,所以如果對它們的使用方式與格式規範不滿意,DIY 一套適合自己業務需求的輕量級工具也是可行。觀察前述幾項工具之後,我們可歸納出實踐指令速查功能需要的部件,

  • 儲存格式:儲存指令的格式和語法,理想上要能滿足用戶瀏覽與程式編譯的需求。
  • 搜尋介面:搜尋指令與自動補全的介面,包含搜尋、瀏覽與預覽功能。
  • 指令輸出:選中指令後的反應,例如執行、印出或是啟動其他程式等。

以我模仿 zsh-fzf-snippetfzf-oneliner-manager 為例。我採用習慣的 markdown 來記錄指令,標題 (#)紀錄摘要,程式碼區塊(``)紀錄指令,無標記段落則作為補充說明。

1
2
3
4
5
6
7
# Print line number X of a file
`head -n <num> <file> | tail -n 1`
https://www.linuxquestions.org/questions/programming-9/print-line-number-x-of-a-file-in-shell-273849/

# Remove duplicate lines from a file
`awk '!seen[$0]++' <file>`
https://linux.cn/article-6881-1.html

我採用模糊搜索工具 fzf 來製作搜尋指令的介面。fzf 能依照部分匹配來搜索文字,所以能免除用正則表達式搜尋字串的負擔。除此之外,也提供了一套方便的介面供用戶搜尋和瀏覽文字檔。

當使用快捷鍵觸發指令速查時,fzf-oneliner-manager 會將指令文件整理成 TSV 檔,其中每一列都包含一條指令的標題、指令內容與補充說明,然後分別陳列標題與補充說明給用戶,讓他們能透過關鍵字或是方向鍵瀏覽要調用的指令。

一旦指令被選中,指令內容會被截取出來,黏貼到用戶的 command Line 上,只要再按下確認,即可觸發這條指令。這項功能有賴 bash 的 bind -x 指令與 READLINE_LINE/READLINE_POINT 變項。

bind -x 能重新映射按鍵以觸發指定的腳本或副程式,此處我把 Ctrl + A 設定成啟動指令速查的快捷鍵。READLINE_LINE 是啟動 bind -x 時,command Line 的內容;而 READLINE_POINT 則是游標所處的位置。換句話說,只要將選中的指令取代既有的 READLINE_LINE,並且把游標挪到指令字串的末端,便能在完成速查後將指令貼到 Command line 上。

1
2
READLINE_LINE="${selected}"			# 用選中的指令替換 command line 既有的內容
READLINE_POINT="${#READLINE_LINE}" # 移動游標到指令字串的末端

因此,有了這樣的工具,管理指令的日子看起來就像這樣:

  1. 「那個解壓縮的指令好像叫 tar 蝦米碗糕的?」,啟動速查。
  2. 找到指令,按下確認執行並解決問題。
  3. 沒找到指令,上網 Google 或是求救 chatgpt。
  4. 把查到的指令補充到指令文件內以便往後搜索。
  5. 無聊時可以打開指令文件緬懷自己的青春,「啊啦啊啦,我小時候可是用 word 紀錄管理 server 的程式碼呢!」。

結論:即使有 AI,

不過現在 chatgpt 或 bing AI 那麼方便,指令速查工具還有用嗎?

我覺得兩者的定位不大一樣。雖然當今生成式 AI 的功能已相當全面,卻仍無法免除溝通的成本。對於陌生議題,獨自構思方法可能比實際解決問題費時,所以上網搜尋、求助他人或是詢問 AI 等借重既有經驗的方法都能縮短整體工時。

然而,隨著用戶熟悉方法,溝通成本便成為額外的負擔。呼應文首那幅四格漫畫,為了解壓縮一份 tar.gz 檔,你要先打關鍵字、按下搜索、點選網頁、複製/貼上、執行,若你用 chatgpt,還得等他做些寒暄和反應的時間。在這種情況下,速查工具能做為很好的捷徑,方便用戶迅速取得常用指令,保持工作的流暢性。

這也是為什麼我覺得用戶要自己維護指令集,因為這樣內容才會符合每個人各自的頻率、需求和合適的搜索關鍵字。當然,等到哪天勞工不用為系統管理或是NGS分析,AI 能自動自發把事情做完的未來時,那又另當別論。