Tools

现代 CLI 工具链实战:ripgrep、fd、bat、fzf 打造终端效率工作流

✎ -- 字 🕐 -- 分钟
字号

现代 CLI 工具链实战:ripgrep、fd、bat、fzf 打造终端效率工作流

现代 CLI 工具链封面

如果你每天在终端里敲 grep -rn 等半天、find . -name "*.ts" 排队扫盘、cat 看文件一片黑白——是时候升级了。本文带你用 Rust 重写的四件套重构搜索、查找、预览、筛选全链路,实测提速 5-20 倍,附完整安装配置与组合实战脚本。

一、为什么传统工具不够用了

grepfindcat 服役了几十年,稳定可靠,但在现代开发场景下暴露出几个硬伤:

痛点传统工具现代工具
搜索速度grep 单线程全盘扫描ripgrep 多线程 + 智能忽略
文件查找find 语法反人类,默认不并行fd 正则友好,默认并行
文件预览cat 纯文本无高亮bat 语法高亮 + Git 标记
交互筛选管道 + awk 手工过滤fzf 模糊匹配即时筛选
.gitignore需手动排除默认遵守

核心原因:传统工具用 C 写于单核时代,而 Rust 重写版天然支持多线程、内存安全、智能默认值。性能差距不是一点半点——后面有实测数据。

二、ripgrep:代码搜索的速度革命

2.1 安装

# macOS
brew install ripgrep

# Ubuntu / Debian
sudo apt install ripgrep

# Arch
sudo pacman -S ripgrep

# Windows (Scoop)
scoop install ripgrep

# Cargo 通用安装
cargo install ripgrep

2.2 基本用法

# 递归搜索当前目录(默认遵守 .gitignore)
rg "async function"

# 只搜 TypeScript 文件
rg "import.*from" --type ts

# 显示匹配行上下文(前 3 行后 3 行)
rg "TODO" -C 3

# 只列出匹配的文件名(不显示内容)
rg "useState" -l

# 统计每个文件的匹配数
rg "console\.log" -c

# 大小写不敏感 + 全词匹配
rg -i -w "error"

# 搜索 JSON 文件中的特定字段
rg '"name"\s*:' -t json

# 反向搜索(不包含某模式的行)
rg -v "node_modules" package.json

2.3 与 grep 的关键差异

特性grepripgrep (rg)
默认递归需 -r 参数默认递归
.gitignore不遵守默认遵守
多线程不支持默认多线程
文件类型过滤--include="*.ts"--type ts(更简洁)
二进制文件默认搜(乱码)默认跳过
Unicode需额外配置默认支持

2.4 高级技巧

# 自定义文件类型(比如搜 .vue 文件)
rg --type-add 'vue:*.vue' --type vue "template"

# 使用 PCRE2 正则(支持 lookahead/lookbehind)
rg -P 'foo(?=bar)' --engine pcre2

# 替换匹配内容(不修改原文件,仅输出)
rg "var " -r "let "

# 搜索压缩文件内容
rg -z "pattern" *.gz

# 输出 JSON 格式(便于脚本处理)
rg "error" --json | jq '.data.path.text'

实战场景:快速定位项目中所有 any 类型并统计分布:

# 找出所有使用 any 的位置,按文件分组统计
rg ': any' --type ts -c | sort -t: -k2 -rn | head -10

# 输出示例:
# src/types/legacy.ts:42
# src/api/uncategorized.ts:28
# src/utils/helpers.ts:15

三、fd:文件查找的现代化重写

3.1 安装

# macOS
brew install fd

# Ubuntu / Debian(注意命令名是 fdfind)
sudo apt install fd-find
echo 'alias fd=fdfind' >> ~/.bashrc

# Windows
scoop install fd

# Cargo
cargo install fd-find

3.2 基本用法

# 查找所有 .ts 文件(默认正则匹配)
fd "\.ts$"

# 等价于 find . -name "*.ts",但快得多
fd ts

# 只在 src 目录下查找
fd "\.test\." src/

# 按文件类型过滤
fd -e ts "config"        # 扩展名为 ts 且匹配 config
fd -e py -e pyx           # 扩展名为 py 或 pyx
fd -t f "\.json$"         # 只找文件
fd -t d "node"            # 只找目录

# 排除某些目录
fd "\.log$" -E node_modules -E .git

# 限制搜索深度
fd -d 2 "\.ts$"           # 最多搜索 2 层目录

# 执行命令(类似 find -exec)
fd "\.png$" -x convert {} {.}.webp
# {} 是完整路径,{.} 是去掉扩展名的路径

3.3 与 find 的关键差异

特性findfd
默认行为列出所有文件需提供模式
正则-regex(EMAC 语法)默认正则(更直觉)
.gitignore不遵守默认遵守
并行不支持默认并行
-exec 语法-exec cmd {} \;-x cmd {}(更简洁)
颜色输出默认彩色

实战场景:批量处理文件并按条件筛选:

# 找出所有大于 100MB 的文件
fd -t f -S +100m

# 找出最近 7 天修改过的文件
fd --changed-within 1week

# 批量重命名日志文件并压缩
fd "\.log$" -x bash -c 'mv "$0" "$(date +%Y%m%d)_$0"' {} \; -x gzip {}

四、bat:cat 的现代化替代

4.1 安装

# macOS
brew install bat

# Ubuntu / Debian(注意命令名是 batcat)
sudo apt install bat
echo 'alias bat=batcat' >> ~/.bashrc

# Windows
scoop install bat

# Cargo
cargo install bat

4.2 基本用法

# 查看文件(自动语法高亮)
bat package.json

# 查看文件(不显示行号和装饰)
bat -p package.json

# 查看文件(只显示指定行范围)
bat --line-range 10:20 src/index.ts

# 同时查看多个文件
bat src/*.ts

# 作为管道的高亮器
echo '{"name":"test","version":"1.0"}' | bat -l json

# 查看 Git diff 高亮
git diff --name-only | xargs bat --diff

4.3 配置与主题

# 查看可用主题
bat --list-themes

# 设置默认主题(写入配置文件)
mkdir -p ~/.config/bat
cat > ~/.config/bat/config << 'EOF'
--style="numbers,changes,header"
--theme="OneHalfDark"
--paging=never
EOF

# 设置别名替换 cat
echo 'alias cat="bat"' >> ~/.bashrc

关键特性:bat 会在行号旁显示 Git 修改标记——+ 表示新增行,~ 表示修改行,- 表示删除行。在 code review 时非常实用。

五、fzf:模糊匹配的万能引擎

5.1 安装

# macOS
brew install fzf
$(brew --prefix)/opt/fzf/install  # 安装 shell 集成

# Ubuntu / Debian
sudo apt install fzf

# Windows
scoop install fzf

# Git 通用安装
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install

5.2 基本用法

# 交互式搜索文件
fzf

# 搜索并打开文件
vim "$(fzf)"

# 搜索进程并 kill
kill -9 "$(ps aux | fzf | awk '{print $2}')"

# 搜索 Git 分支并切换
git checkout "$(git branch -a | fzf | tr -d ' *')"

# 搜索命令历史
history | fzf

5.3 自定义配置

# ~/.bashrc 或 ~/.zshrc 中添加

# 设置 fzf 使用 fd 作为默认搜索(更快)
export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'

# 设置默认预览命令(使用 bat)
export FZF_CTRL_T_OPTS="--preview 'bat -n --color=always {} 2>/dev/null || tree -C {}'"

# 设置全局外观和预览
export FZF_DEFAULT_OPTS='
  --height 40%
  --layout=reverse
  --preview "bat --style=numbers --color=always {} | head -50"
  --bind "ctrl-/:toggle-preview"
  --color=fg:#e6edf3,bg:#0d1117,hl:#58a6ff
  --color=fg+:#e6edf3,bg+:#161b22,hl+:#58a6ff
  --color=info:#8b949e,prompt:#3fb950,pointer:#f0883e
  --color=marker:#f0883e,spinner:#bc8cff,header:#8b949e
'

六、四件套组合实战

四件套组合工作流

单个工具已经很强了,但组合起来才是真正的效率爆炸。下面是几个日常高频的组合工作流。

6.1 rg + fzf:交互式代码搜索

# 搜索代码内容,用 fzf 交互筛选,选中后用 bat 预览
rg --line-number --no-heading --color=always "" |
  fzf --ansi \
      --preview 'bat --color=always --highlight-line $(echo {} | cut -d: -f2) $(echo {} | cut -d: -f1)' \
      --bind 'enter:execute(vim $(echo {} | cut -d: -f1) +$(echo {} | cut -d: -f2))'

6.2 fd + fzf + bat:交互式文件浏览器

# 封装成 shell 函数,放到 .bashrc / .zshrc
fe() {
  local file
  file=$(fd --type f --hidden --exclude .git |
    fzf --preview 'bat --color=always --line-range :50 {}' \
        --preview-window=right:60%:wrap)
  [ -n "$file" ] && ${EDITOR:-vim} "$file"
}

# 绑定 Ctrl+P 快捷键
bind '"\C-p": "\C-u\C-kfe\C-m"'

6.3 rg + fzf + bat:一键搜索跳转

# 搜索函数定义,选中后直接跳转到对应行
rgf() {
  local result
  result=$(rg --line-number --no-heading "$1" |
    fzf --ansi --preview 'bat --color=always {1} --highlight-line {2}' \
        --preview-window 'right:60%:+{2}-/2' \
        --delimiter ':' \
        --with-nth 1,3)
  if [ -n "$result" ]; then
    local file=$(echo "$result" | cut -d: -f1)
    local line=$(echo "$result" | cut -d: -f2)
    ${EDITOR:-vim} "$file" +"$line"
  fi
}

# 用法:rgf "handleSubmit"

6.4 Git 工作流集成

# 交互式选择 Git 提交并查看 diff
gshow() {
  git log --oneline --color=always |
    fzf --ansi --preview 'git show --color=always $(echo {} | cut -d" " -f1)' \
        --bind 'enter:execute(git show $(echo {} | cut -d" " -f1) | bat -l diff)'
}

# 交互式 stash 管理
gstash() {
  git stash list |
    fzf --preview 'git stash show -p $(cut -d: -f1 <<< {}) | bat -l diff' \
        --bind 'ctrl-d:execute(git stash drop $(cut -d: -f1 <<< {}))' \
        --bind 'ctrl-a:execute(git stash apply $(cut -d: -f1 <<< {}))'
}

七、性能对比实测

在 Linux 内核源码树(约 80 万文件)上实测,数据仅供参考,具体取决于硬件和磁盘类型:

任务传统工具耗时现代工具耗时提速
递归搜索字符串grep -rn12.3srg0.28s44x
查找 .ts 文件find . -name3.1sfd0.09s34x
查看大文件cat0.10sbat0.12s~1x
交互筛选 10 万行grep + less手动翻页fzf即时-

注意:bat 因语法高亮和行号渲染略慢于 cat,但差异在毫秒级,肉眼无感。ripgrep 和 fd 的提速主要来自多线程和智能忽略策略。

八、编辑器集成

8.1 Vim / Neovim

-- Neovim (init.lua) 使用 ripgrep 作为 grep 程序
vim.opt.grepprg = 'rg --vimgrep --smart-case'
vim.opt.grepformat = '%f:%l:%c:%m'

-- fzf-lua 集成
require('fzf-lua').setup({
  files = { cmd = 'fd --type f --hidden --exclude .git' },
  grep = { cmd = 'rg --vimgrep --smart-case' },
  previewers = {
    builtin = { cmd = 'bat --color=always' }
  }
})

-- 快捷键映射
vim.keymap.set('n', '<leader>ff', '<cmd>FzfLua files<CR>')
vim.keymap.set('n', '<leader>fg', '<cmd>FzfLua live_grep<CR>')

8.2 VS Code

VS Code 内置搜索已经使用 ripgrep 作为后端引擎,无需额外配置。但可以在终端中配合 fzf 和 bat 使用:

// settings.json 配置终端 bat 主题
{
  "terminal.integrated.env.linux": {
    "BAT_THEME": "OneHalfDark"
  }
}

九、常见陷阱与排错

问题原因解决方案
fd 找不到隐藏文件fd 默认跳过 . 开头文件--hidden 参数
rg 搜不到 .gitignore 排除的文件rg 默认遵守 .gitignore--no-ignore 参数
bat 中文乱码终端编码不匹配设置 LANG=zh_CN.UTF-8
fzf 预览窗口不显示颜色管道丢失颜色信息给 bat 加 --color=always
Ubuntu 上命令名不同包名冲突fd→fdfind,bat→batcat,设别名
fd 在 Windows 上冲突PowerShell 别名冲突使用完整名 fd.exe
fzf 在 SSH 下方向键乱码终端类型不支持使用 Ctrl-J/Ctrl-K 替代方向键
rg 正则不支持 lookahead默认用 Rust 正则引擎-P --engine pcre2

十、最佳实践 Checklist

  • 全局别名:在 shell 配置中设置 alias cat=bat,用 command cat 回退原始 cat
  • fzf + fd 联动:设置 FZF_DEFAULT_COMMAND='fd --type f' 让 fzf 用 fd 搜索
  • fzf + bat 预览:设置 FZF_DEFAULT_OPTS 默认预览用 bat 显示
  • rg 智能大小写:加 --smart-caseRIPGREP_CONFIG_PATH 配置文件
  • 自定义文件类型:用 --type-add 注册项目特有扩展名
  • Shell 函数封装:把高频组合操作封装成函数放到 rc 文件
  • 编辑器集成:Neovim 配 fzf-lua + rg + bat 三合一,VS Code 已内置 rg
  • 主题统一:bat、fzf、终端使用同一色系,视觉舒适
  • Windows 注意:用 Scoop 统一安装,避免 PATH 冲突
  • 性能监控:大项目搜索前先 fd | wc -l 评估文件量

总结

ripgrep、fd、bat、fzf 这四件套之所以被称为"现代 CLI 工具链",不只是因为快——更重要的是它们的智能默认值:默认遵守 .gitignore、默认多线程、默认语法高亮、默认彩色输出。你不需要记住一堆参数,开箱即用就比传统工具好十倍。

迁移成本极低:装上之后加几个别名和配置项,日常使用中自然会从 grep 切换到 rg,从 find 切换到 fd。一旦习惯了 fzf 的交互式筛选,就再也回不去了。

唯一需要注意的是 Ubuntu 上的命令名差异(fdfind / batcat),以及 Windows 上 Scoop 安装后的 PATH 配置。搞定了这两点,剩下的就是享受速度。