fzf终端模糊搜索神器

fzf (Fuzzy Finder) 是一款通用的命令行模糊搜索工具,能够通过模糊匹配关键词快速定位文件、历史命令、进程、Git 提交记录等。

它的核心设计哲学遵循 UNIX 管道理念:作为一个通用的交互式过滤器,接收标准输入(stdin),处理后将结果输出到标准输出(stdout)。这种设计使其能够与 findgrephistory 等任何命令无缝集成。

核心特性:

  • 通用性:默认列出当前目录文件名,配合 ripgrepgrep 可搜索文件内容。
  • Shell 集成:安装后默认接管 Ctrl + R,将枯燥的历史命令回溯转化为高效的交互式搜索体验。

1. 工作原理

fzf 的工作流本质上是一个 “ 输入 -> 过滤 -> 执行 “ 的管道处理过程。

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#4F46E5', 'primaryTextColor': '#fff', 'primaryBorderColor': '#3730A3', 'lineColor': '#6366F1', 'secondaryColor': '#10B981', 'tertiaryColor': '#F59E0B'}}}%%
flowchart LR
    Input["输入源<br/>(find, history, ps)"] -->|Pipe| Filter["FZF 模糊交互<br/>(筛选/预览)"]
    Filter -->|Select| Output["输出结果<br/>(文件路径, PID)"]
    Output -->|Arg| Action["执行命令<br/>(vim, kill, cd)"]

    classDef primary fill:#4F46E5,stroke:#3730A3,color:#fff
    classDef success fill:#10B981,stroke:#059669,color:#fff
    classDef warning fill:#F59E0B,stroke:#D97706,color:#fff

    class Input warning
    class Filter primary
    class Output success
    class Action warning

2. Fzf 使用

2.1 安装

使用 Git 仓库直接安装是通用的方式:

1
2
3
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install
source ~/.zshrc # 或 ~/.bashrc

2.2 基础使用

安装完成后,直接在终端执行 fzf 即可体验基础的文件搜索功能。常用组合:

  1. 直接打开文件

    1
    2
    vim $(fzf)          # 搜索并使用 Vim 打开
    vim $(fzf --height 40%) # 以 40% 高度的下方窗口打开,体验更好
  2. Shell 快捷键

    • Ctrl + R: 搜索历史命令(替换默认的历史搜索)。
    • Ctrl + T: 快速查找文件并粘贴到命令行。
    • Alt + C: 快速进入目录。
  3. 模糊补全
    Bash 和 Zsh 支持 ** 触发模糊补全:

    • vim **<TAB>: 模糊搜索文件并补全路径。
    • cd **<TAB>: 模糊搜索目录并补全。
    • ssh **<TAB>: 搜索主机名。

    image-20210318000439297

  4. 实时预览
    使用 --preview 参数可以在搜索时预览文件内容:

    1
    fzf --preview 'cat {}'
  5. 管道组合

    1
    2
    3
    ps -ef | fzf        # 搜索进程
    seq 100 | fzf # 搜索数字序列
    history | fzf # 手动搜索历史

2.3 搜索语法

fzf 支持灵活的搜索模式,默认为模糊匹配。

模式语法描述示例
模糊匹配sbtrkt匹配包含字符序列的项sbtrkt 匹配 subtrack
精确匹配'wild精确匹配完整单词'wild 匹配 wild
前缀匹配^music匹配以该字符串开头^music 匹配 music-app
后缀匹配.mp3$匹配以该字符串结尾.mp3$ 匹配 song.mp3
反向匹配!fire排除包含该字符串的项!fire 排除 firewall
反向前缀!^music排除以该字符串开头
反向后缀!.mp3$排除以该字符串结尾

2.4 与 Tmux 结合

fzf 自带 fzf-tmux 脚本,可以在 Tmux 面板中打开。默认行为是分割当前面板,这可能会破坏布局。推荐配置为弹出窗口(Popup Window)模式,体验更佳。

参考配置:Fzf Tmux配置

2.5 高级配置:文件打开增强

.zshrc.bashrc 中添加以下函数,实现增强的文件打开功能:

  • Ctrl-o: 使用系统默认应用打开(如 macOS 的 open)。
  • Ctrl-E (或回车): 使用 $EDITOR (如 Vim) 打开。
1
2
3
4
5
6
7
8
9
10
11
# Modified version where you can press  
# - CTRL-O to open with `open` command,
# - CTRL-E or Enter key to open with the $EDITOR
fo() {
IFS=$'\n' out=("$(fzfp --preview 'cat {}' --query="$1" --exit-0 --expect=ctrl-o,ctrl-e)")
key=$(head -1 <<< "$out")
file=$(head -2 <<< "$out" | tail -1)
if [ -n "$file" ]; then
[ "$key" = ctrl-o ] && open "$file" || ${EDITOR:-vim} "$file"
fi
}

image-20210318231156159

2.6 高级配置:目录切换增强

结合 find 命令排除隐藏文件,并实现快速目录跳转。

1
2
3
4
5
6
7
8
# fd (Find Dir): 查找并进入目录
fd() {
local dir
# 查找目录,排除隐藏目录 (.git 等)
dir=$(find ${1:-.} -path '*/\.*' -prune \
-o -type d -print 2> /dev/null | fzf +m) &&
cd "$dir"
}

2.7 高级配置:全文内容搜索

结合 ripgrep (rg) 实现高效的全文内容搜索与预览。

1
2
3
4
5
6
7
8
9
# fif (Find In File): 在文件中搜索字符串
# 用法: fif <searchTerm>
fif() {
if [ ! "$#" -gt 0 ]; then echo "Need a string to search for!"; return 1; fi

# 使用 rg 搜索包含匹配项的文件,传给 fzf
# fzf 预览窗口中使用 rg 高亮显示匹配行及其上下文
rg --files-with-matches --no-messages "$1" | fzf --preview "highlight -O ansi -l {} 2> /dev/null | rg --colors 'match:bg:yellow' --ignore-case --pretty --context 10 '$1' || rg --ignore-case --pretty --context 10 '$1' {}"
}

3. Vim 中使用 Fzf

3.1 安装

推荐使用 vim-plug 管理插件:

1
2
3
4
5
6
7
8
" 安装 fzf 二进制文件
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
" 安装 fzf vim 集成插件
Plug 'junegunn/fzf.vim'

" 常用快捷键映射
nnoremap <leader>fo :Files<CR> " 查找文件
nnoremap <leader>fif :Rg<CR> " 全文搜索

3.2 常用命令

  • :Files: 模糊搜索当前项目文件(类似于 VS Code 的 Ctrl+P)。
    image-20210318230744605

  • :Rg: 使用 Ripgrep 搜索项目内容。
    image-20210318230855552

  • :Buffers: 搜索当前打开的缓冲区。

  • :History: 搜索最近打开的文件历史。

4. 参考资料