10  現代 CLI 工具集

傳統 Unix 工具的現代替代品,更快、更好用、更漂亮。

10.1 安裝所有工具

10.1.1 背景(問題發現)

傳統 Unix 工具(如 find、grep、cat、ls)雖然功能強大,但在現代開發環境中面臨幾個問題:

  • 速度慢:在大型專案中搜尋檔案或文字耗時過長
  • 語法複雜:find 和 grep 的選項參數難以記憶
  • 輸出單調:缺乏顏色和視覺層次,難以快速辨識資訊
  • 缺乏智能:無法記住使用習慣或提供互動式介面

10.1.2 方法

使用 Homebrew 一次性安裝所有現代 CLI 工具替代品。這些工具大多使用 Rust 語言開發,具有以下特點:

  • 高效能:編譯型語言帶來的速度優勢
  • 友善語法:更符合直覺的命令選項
  • 美觀輸出:支援顏色、圖標和語法高亮
  • 智能功能:自動排除 .gitignore、學習使用習慣等

10.1.3 結果(程式碼)

brew install fd ripgrep bat eza zoxide fzf yazi lsd

10.1.4 討論/延伸

工具清單: - fd:取代 find,檔案搜尋 - ripgrep:取代 grep,文字搜尋 - bat:取代 cat,檔案檢視 - eza:取代 ls,目錄列表 - zoxide:取代 cd,智能目錄跳轉 - fzf:模糊搜尋工具 - yazi:現代檔案管理器 - lsd:另一個 ls 替代品(可與 eza 擇一使用)

注意事項: - 安裝後不會覆蓋原始工具,兩者可並存 - 建議透過 shell 別名逐步過渡,避免影響現有腳本 - 某些工具可能需要額外設定才能發揮完整功能

10.2 fd:更好的 find

10.2.1 背景(問題發現)

傳統 find 指令的問題: - 語法冗長find . -name "*.md" 需要記住多個選項 - 速度較慢:未針對現代檔案系統優化 - 缺乏智能:不會自動忽略 .gitignore 中的檔案 - 輸出混亂:沒有顏色區分,難以快速掃視結果

在大型專案中搜尋特定檔案時,這些問題會嚴重影響開發效率。

10.2.2 方法

fd 採用簡化的語法設計和智能預設行為:

核心概念: - 簡潔語法fd pattern 即可搜尋,預設即為遞迴搜尋 - 智能過濾:自動讀取 .gitignore,排除不需要的檔案 - 彩色輸出:使用顏色區分檔案類型 - 正規表達式:預設支援正規表達式搜尋

常用選項: - -e, --extension:指定副檔名 - -d, --max-depth:限制搜尋深度 - -E, --exclude:排除特定模式 - -t, --type:指定檔案類型(f=檔案, d=目錄)

10.2.3 結果(程式碼)

# 搜尋所有 .md 檔案
fd -e md

# 搜尋名稱包含 config 的檔案
fd config

# 限制深度
fd -d 2 -e js

# 排除目錄
fd -E node_modules -e ts

10.2.4 討論/延伸

進階用法

# 只搜尋目錄
fd -t d config

# 搜尋隱藏檔案
fd -H pattern

# 執行命令(類似 find -exec)
fd -e jpg -x convert {} {.}.png

# 組合多個條件
fd -e md -e txt --max-depth 3

效能比較: 在包含 100,000 個檔案的專案中,fd 通常比 find 快 2-10 倍,因為它使用平行搜尋和智能快取。

注意事項: - 預設會忽略 .gitignore,使用 -I 關閉此行為 - 預設隱藏 hidden 檔案,使用 -H 顯示 - 與 find 不同,預設使用正規表達式而非 glob 模式

10.3 ripgrep:更快的 grep

10.3.1 背景(問題發現)

傳統 grep 在現代開發中的限制: - 速度瓶頸:在大型程式碼庫中搜尋耗時過長 - 功能分散:需要組合 grep、egrep、fgrep 等不同變體 - 缺乏智能:會搜尋 node_modules、.git 等無關目錄 - 輸出單調:沒有檔案類型辨識和語法高亮

當在包含數萬個檔案的專案中搜尋特定函數或變數時,這些問題會顯著降低生產力。

10.3.2 方法

ripgrep(簡稱 rg)透過以下策略實現極致速度:

核心技術: - 平行搜尋:使用多執行緒同時搜尋多個檔案 - 記憶體映射:使用 mmap 提升大檔案讀取效率 - 智能過濾:預設尊重 .gitignore 和其他忽略檔案 - 正規表達式引擎:使用高效的 Rust regex 函式庫

關鍵選項: - -l, --files-with-matches:只顯示包含匹配的檔案名 - -t, --type:依檔案類型過濾(支援 40+ 種語言) - -c, --count:顯示每個檔案的匹配次數 - -r, --replace:預覽替換結果(不修改檔案)

10.3.3 結果(程式碼)

# 搜尋文字
rg "pattern"

# 只顯示檔名
rg -l "pattern"

# 指定檔案類型
rg -t py "import"

# 計數
rg -c "pattern"

# 搜尋並取代(預覽)
rg "old" -r "new"

10.3.4 討論/延伸

進階搜尋技巧

# 多行搜尋
rg -U "pattern1.*\n.*pattern2"

# 搜尋時忽略大小寫
rg -i "pattern"

# 搜尋隱藏檔案和 gitignore 的檔案
rg --hidden --no-ignore "pattern"

# 只搜尋特定目錄
rg "pattern" src/ tests/

# 顯示前後文(各 3 行)
rg -C 3 "pattern"

# 反向搜尋(不包含 pattern 的行)
rg -v "pattern"

實際應用場景

# 找出所有使用某個函數的地方
rg "myFunction\(" -t js -t ts

# 找出 TODO 標記
rg "TODO|FIXME|HACK" -i

# 統計各檔案的匹配數量
rg -c "import" -t py --sort path

效能數據: 在包含 1 GB 原始碼的專案中,ripgrep 通常比 grep 快 5-10 倍,比 ack 快 15-30 倍。

注意事項: - 預設會忽略二進位檔案,使用 -a 包含所有檔案 - 與 grep 不同,預設使用 PCRE2 正規表達式 - 可用 --type-list 查看所有支援的檔案類型 - 搜尋並取代只是預覽,需搭配其他工具(如 sed)實際修改

10.4 bat:帶語法高亮的 cat

10.4.1 背景(問題發現)

傳統 cat 指令的限制: - 缺乏語法高亮:無法快速辨識程式碼結構 - 沒有行號顯示:不易定位特定行或與編輯器對照 - 無法分頁檢視:大檔案難以閱讀 - 缺少 Git 整合:無法顯示檔案修改狀態

當需要快速檢視原始碼檔案或在終端機中進行程式碼審查時,純文字輸出難以快速理解內容。

10.4.2 方法

bat 是一個增強版的 cat,提供類似程式碼編輯器的閱讀體驗:

核心功能: - 語法高亮:支援 200+ 種程式語言和檔案格式 - Git 整合:在邊欄顯示檔案修改、新增、刪除的行 - 自動分頁:大檔案自動使用 less 風格的分頁器 - 行號顯示:預設顯示行號,方便定位

常用選項: - -r, --line-range:只顯示特定行號範圍 - -n, --number:只顯示行號,不顯示 Git 修改 - -p, --plain:純文字模式(類似原始 cat) - -l, --language:手動指定語法高亮語言

10.4.3 結果(程式碼)

# 顯示檔案
bat file.py

# 顯示行號範圍
bat -r 10:20 file.py

# 與其他命令組合
rg "pattern" -l | xargs bat

10.4.4 討論/延伸

進階用法

# 顯示多個檔案
bat src/*.js

# 顯示非印字字元(空白、Tab)
bat -A file.txt

# 純文字模式(取代 cat)
bat -p file.txt

# 指定主題
bat --theme="Monokai Extended" file.py

# 列出所有可用主題
bat --list-themes

# 顯示特定語言的語法
bat -l json config.txt

實際應用場景

# 快速程式碼審查
git diff --name-only | xargs bat

# 檢視搜尋結果的內容
rg -l "TODO" | xargs bat -r :50

# 比較兩個檔案(使用 diff 高亮)
bat --diff file1.js file2.js

# 管道輸入也支援語法高亮
curl -s https://api.github.com/users/htlin | bat -l json

設定別名

# 完全取代 cat
alias cat='bat --paging=never'

# 保留分頁功能
alias less='bat'

客製化設定: 在 ~/.config/bat/config 中設定預設行為:

--theme="TwoDark"
--style="numbers,changes,header"
--italic-text=always

注意事項: - 語法高亮需要終端機支援 24-bit 顏色 - 預設會分頁,使用 --paging=never 關閉 - 可用 bat --list-languages 查看所有支援的語言 - 與其他指令組合時,建議使用 -p 避免分頁中斷流程

10.5 eza/lsd:現代化的 ls

10.5.1 背景(問題發現)

傳統 ls 指令的痛點: - 輸出單調:缺乏顏色和圖標,難以快速辨識檔案類型 - 資訊不足:無法直觀顯示 Git 狀態、檔案權限等資訊 - 功能有限:樹狀顯示需要另外安裝 tree 指令 - 使用體驗差:選項不直覺,需要記憶複雜的參數組合

在日常檔案瀏覽中,這些限制導致需要頻繁使用其他工具輔助才能獲取完整資訊。

10.5.2 方法

ezalsd 是兩個現代化的 ls 替代品,提供更豐富的視覺體驗:

eza 核心特色: - 圖標顯示:使用 Nerd Fonts 顯示檔案類型圖標 - Git 整合:顯示檔案的 Git 狀態(修改、新增、忽略) - 彩色輸出:依檔案類型自動上色 - 樹狀檢視:內建樹狀目錄顯示功能

lsd 核心特色: - LSDeluxe:更華麗的視覺效果和圖標系統 - 類似功能:與 eza 功能相近,風格略有不同 - 效能優異:Rust 實作,速度快

常用選項: - -l:長格式,顯示詳細資訊 - -a:顯示隱藏檔案(以 . 開頭的檔案) - --tree:樹狀顯示目錄結構 - --git:顯示 Git 狀態欄位

10.5.3 結果(程式碼)

# 基本列表
eza

# 長格式
eza -l

# 包含隱藏檔案
eza -la

# 樹狀顯示
eza --tree

# 或使用 lsd
alias tree='lsd --tree'

10.5.4 討論/延伸

eza 進階用法

# 顯示 Git 狀態
eza -l --git

# 依修改時間排序
eza -l --sort=modified

# 顯示檔案大小(人類可讀格式)
eza -lh

# 樹狀顯示並限制深度
eza --tree --level=2

# 只顯示目錄
eza -D

# 顯示完整時間資訊
eza -l --time-style=long-iso

# 群組目錄在前
eza -l --group-directories-first

lsd 進階用法

# 顯示完整資訊
lsd -la

# 樹狀顯示
lsd --tree

# 依大小排序
lsd -lS

# 遞迴顯示所有檔案
lsd -R

# 只顯示目錄
lsd -d */

實用別名設定

# 使用 eza
alias ls='eza --icons'
alias ll='eza -l --icons --git'
alias la='eza -la --icons --git'
alias lt='eza --tree --icons --git-ignore'
alias l='eza -lah --icons --git'

# 或使用 lsd
alias ls='lsd'
alias ll='lsd -l'
alias la='lsd -la'
alias tree='lsd --tree'

eza vs lsd 選擇: - eza:更活躍的開發、更多功能、Git 整合較好 - lsd:視覺效果更華麗、設定更簡單 - 建議:兩者都可試用,選擇符合個人喜好的即可

注意事項: - 需要安裝支援 Nerd Fonts 的字型才能正確顯示圖標 - 推薦字型:FiraCode Nerd Font、JetBrains Mono Nerd Font - 某些終端機可能需要設定字型才能正確顯示 - 兩者功能相似,通常不需要同時使用

10.6 zoxide:智能 cd

10.6.1 背景(問題發現)

傳統 cd 指令的使用痛點: - 需要完整路徑:必須輸入完整或相對路徑才能切換目錄 - 無法記憶習慣:無法記住常用目錄,每次都要重新輸入 - 效率低落:在深層目錄結構中來回切換耗時費力 - 缺乏智能:無法根據使用頻率智能推薦目錄

例如從 ~/projects/work/backend/src/controllers 切換到 ~/projects/personal/frontend/components,需要輸入冗長的路徑。

10.6.2 方法

zoxide 是一個智能目錄跳轉工具,透過學習使用習慣提供快速導航:

核心機制: - Frecency 演算法:結合使用頻率(Frequency)和最近使用時間(Recency) - 模糊匹配:只需輸入部分目錄名稱即可匹配 - 自動學習:追蹤每次 cd 操作,建立使用模式資料庫 - 互動選擇:當匹配多個目錄時,提供互動式選擇介面

使用方式: - z <關鍵字>:跳轉到匹配的目錄 - zi <關鍵字>:互動式選擇(使用 fzf) - z -:返回上一個目錟 - zoxide query <關鍵字>:查詢匹配結果但不跳轉

10.6.3 結果(程式碼)

# 初始化
eval "$(zoxide init zsh)"

# 使用
z projects      # 跳到最常用的 projects 目錄
zi              # 互動式選擇

# 它會學習你的習慣
cd ~/projects/myapp
cd ~/documents
z myapp         # 直接跳回 ~/projects/myapp

10.6.4 討論/延伸

完整設定步驟

# 1. 安裝 zoxide
brew install zoxide

# 2. 在 shell 設定檔中初始化(根據你使用的 shell)
# Zsh (~/.zshrc)
eval "$(zoxide init zsh)"

# Bash (~/.bashrc)
eval "$(zoxide init bash)"

# Fish (~/.config/fish/config.fish)
zoxide init fish | source

# 3. 安裝 fzf(用於互動式選擇)
brew install fzf  # https://github.com/junegunn/fzf

進階用法

# 查詢但不跳轉
zoxide query myapp

# 列出所有記錄的目錄(按分數排序)
zoxide query -l

# 刪除某個路徑記錄
zoxide remove /path/to/dir

# 手動新增路徑
zoxide add /path/to/dir

# 使用多個關鍵字(更精確匹配)
z work backend controllers

# 直接跳到子目錄
z myapp src

別名設定

# 完全取代 cd(在 zoxide init 時加上 --cmd cd)
eval "$(zoxide init zsh --cmd cd)"
# 現在 cd 就是 zoxide 了

# 或保留 cd,另外建立短別名
alias j='z'    # 使用 j 跳轉(類似 autojump)

實際使用場景

# 假設你的工作流程
cd ~/projects/company/backend/api/controllers
cd ~/projects/personal/blog/content/posts
cd ~/documents/notes/programming

# 幾天後,這些目錄都有使用記錄
z api          # 跳到 ~/projects/company/backend/api
z blog         # 跳到 ~/projects/personal/blog
z prog         # 跳到 ~/documents/notes/programming

# 如果有衝突(多個目錄都叫 api)
zi api         # 顯示所有匹配的目錄,可互動選擇

與其他工具整合

# 組合 fzf 建立更強大的目錄選擇器
function fcd() {
  local dir
  dir=$(zoxide query -l | fzf --height 40% --reverse)
  [ -n "$dir" ] && cd "$dir"
}

Frecency 演算法說明: - 每次 cd 到某目錄,該目錄的分數會增加 - 分數會隨時間衰減,確保最近使用的目錄優先 - 使用頻率高且最近使用過的目錄會得到最高分數 - 數學公式:score = frequency * (recent_factor ^ time_since_last_access)

注意事項: - 需要一段時間累積使用記錄才能發揮最大效用 - 第一次使用時,目錄必須先用 cd 訪問過才能被記錄 - 資料庫儲存在 ~/.local/share/zoxide/db.zo - 如果發現匹配結果不理想,可以手動編輯或刪除記錄

10.7 yazi:現代檔案管理器

10.7.1 背景(問題發現)

傳統檔案管理的限制: - GUI 檔案管理器:在遠端伺服器無法使用,需要頻繁切換視窗 - 純 CLI 操作:複製、移動、重新命名等操作需要記憶複雜指令 - 缺乏預覽:無法在終端機中預覽圖片、PDF、影片等檔案 - 效率低落:在大量檔案中尋找目標檔案耗時費力

需要一個結合 GUI 直覺性和 CLI 效率的解決方案,特別是在 SSH 連線或終端機工作流程中。

10.7.2 方法

yazi 是用 Rust 開發的現代終端檔案管理器,提供類似 GUI 的體驗:

核心特色: - Miller Columns 佈局:三欄式介面(父目錄、當前目錄、預覽) - 豐富預覽:支援圖片、PDF、影片、壓縮檔、程式碼等 - Vim 快捷鍵:使用 hjkl 導航,符合 Vim 使用者習慣 - 極致效能:Rust 實作,啟動快速、操作流暢

整合設計: - 目錄切換整合:離開 yazi 時可保留當前目錄 - Shell 包裝函數:透過函數包裝實現與 shell 的無縫整合 - 外部程式調用:可執行系統指令或自訂腳本

預覽支援: - 圖片(PNG、JPG、GIF、WEBP) - 影片(透過 ffmpegthumbnailer) - PDF 文件 - 壓縮檔內容 - 程式碼語法高亮 - Markdown 渲染

10.7.3 結果(程式碼)

# 安裝
brew install yazi

# 使用(帶目錄切換)
function ya() {
  local tmp="$(mktemp -t "yazi-cwd.XXXXX")"
  yazi "$@" --cwd-file="$tmp"
  if cwd="$(cat -- "$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then
    cd -- "$cwd"
  fi
  rm -f -- "$tmp"
}

10.7.4 討論/延伸

基本快捷鍵

導航操作:
  h/j/k/l    左/下/上/右移動(Vim 風格)
  gg/G       跳到第一個/最後一個檔案
  /          搜尋檔案
  z          跳轉到目錄(整合 zoxide)

檔案操作:
  y          複製(yank)
  x          剪下
  p          貼上
  d          刪除(需確認)
  r          重新命名
  Space      選取/取消選取
  v          選取模式(批次選取)

檢視操作:
  Enter      進入目錄或開啟檔案
  i          預覽當前檔案
  q          離開 yazi

進階操作:
  :          執行指令模式
  !          執行 shell 指令
  t          建立新標籤頁
  1-9        切換標籤頁

安裝預覽依賴

# 圖片預覽(選擇其一)
brew install ueberzugpp        # 推薦
brew install kitty             # 使用 kitty 終端機

# PDF 預覽
brew install poppler

# 影片縮圖
brew install ffmpegthumbnailer

# 壓縮檔預覽
brew install p7zip jq

# 程式碼高亮(yazi 內建支援 bat)
brew install bat  # https://github.com/sharkdp/bat

設定檔客製化

# 設定檔位置:~/.config/yazi/yazi.toml
# 建立設定檔
mkdir -p ~/.config/yazi
cat > ~/.config/yazi/yazi.toml << 'EOF'
[manager]
ratio = [1, 4, 3]  # 調整三欄寬度比例
sort_by = "modified"
sort_reverse = true
show_hidden = true

[preview]
max_width = 1000
max_height = 1000

[opener]
# 自訂開啟程式
edit = [
  { run = 'nvim "$@"', block = true }
]
EOF

進階整合範例

# 與 fzf 整合:快速跳轉並開啟 yazi
function yf() {
  local dir=$(fd -t d | fzf --preview 'eza -T {} | head -50')  # fd, fzf, eza 整合
  [ -n "$dir" ] && ya "$dir"
}

# 快速開啟最近目錄
function yr() {
  local dir=$(zoxide query -l | fzf)  # zoxide, fzf 整合
  [ -n "$dir" ] && ya "$dir"
}

# 搭配 ripgrep 找檔案後用 yazi 開啟
function yz() {
  local file=$(rg --files | fzf)  # ripgrep, fzf 整合
  [ -n "$file" ] && ya "$(dirname "$file")"
}

實際應用場景

# 快速整理下載資料夾
ya ~/Downloads

# SSH 連線到伺服器後管理檔案
ssh server
ya /var/www/html

# 在專案中快速找檔案並編輯
ya ~/projects/myapp

# 批次重新命名檔案
# 1. 進入 yazi
# 2. 使用 Space 或 v 模式選取多個檔案
# 3. 按 r 進入批次重新命名模式

yazi vs ranger 比較: - 效能:yazi 啟動和操作速度遠快於 ranger(Python 寫的) - 預覽:yazi 對圖片和影片預覽支援更好 - 現代化:yazi 設計更現代,設定更簡潔 - 社群:yazi 較新但發展快速,ranger 較成熟

注意事項: - 圖片預覽需要支援的終端機(iTerm2、Kitty、WezTerm) - 某些預覽功能需要額外安裝依賴套件 - ya 函數必須定義在 shell 設定檔中才能保留目錄切換 - 在 tmux 中使用時,圖片預覽可能需要額外設定

10.8 工具對照表

傳統工具 現代替代 主要優勢
find fd 更快、語法簡潔
grep ripgrep 極快、自動忽略
cat bat 語法高亮
ls eza/lsd 圖標、顏色
cd zoxide 智能跳轉
ranger yazi 更快、Rust 寫的

10.9 實作練習

  1. 安裝所有現代工具
  2. 設定 shell 別名:
alias cat='bat'
alias ls='eza'
alias tree='lsd --tree'
  1. 初始化 zoxide 並使用一週
  2. 嘗試用 yazi 管理檔案
Tip效能提示

這些工具大多用 Rust 寫成,效能比傳統工具好很多。在大型專案中差異尤其明顯。