每天在终端里,我们都在反复做同一件事:找文件、翻历史、切 Git 分支、kill 进程。传统做法是靠记忆完整路径,或者用 find / grep 拼一长串正则。fzf 是一个用 Go 写的模糊查找器(fuzzy finder),它把”猜完整名字”变成”输入几个关键字即时过滤”。只要敲 fzf,当前目录的文件、命令历史、任意管道输出,都能用交互式列表实时筛选。它的匹配是”子序列模糊匹配”——你输入 srcutil,它能命中 src/utils/helper.go,不要求连续也不要求顺序严格,只要求字符依次出现,因此容错极高。配合 fd、ripgrep、bat,它能把朴素的 Shell 升级成带预览和补全的现代开发环境,体验接近 IDE 里的快速打开(Quick Open)。
一、为什么需要 fzf:给命令行装一个”搜索引擎”
命令行工具很强,但”定位”一直是短板。cd 进深层目录要靠 Tab 一层层补全,git checkout 要背全分支名,kill 要先用 ps 抄 PID。fzf 的核心价值,是把所有这些”先列后选”的动作合并成一步交互式筛选:你只管打字,它负责过滤和高亮。它不依赖数据库索引,纯内存模糊匹配,十万级条目也能毫秒响应,因此特别适合在仓库、日志、进程列表里”随手捞”。它也不是只有一个花哨界面——本质上 fzf 是个过滤器:读 stdin、写 stdout,所以可以无缝嵌进任何管道,这正是它能和 Unix 哲学完美融合的原因。和传统的 select 菜单或 peco、skim 相比,fzf 胜在零依赖、速度快、补全与键位开箱即用。
二、安装与最小可用
fzf 单文件二进制,安装极简。macOS 用 Homebrew,Linux 用包管理器或源码 clone 即可。install 脚本会顺手帮你绑定 Ctrl-R 历史搜索和 **<TAB> 路径补全。除了这两个默认键位,fzf 还默认接管 Ctrl-T(把选中文件放进命令行参数)和 Alt-C(直接进入选中目录),三个键位覆盖了”历史 / 文件 / 目录”三大高频场景。在服务器上如果没 root,用源码 clone 到 ~/.fzf 再运行 install 即可,无需 sudo。装完后建议重开一个终端,确认 Ctrl-R 能弹出带高亮的列表,说明键位已生效。
brew install fzf # macOS
# Ubuntu / Debian
apt-get install fzf
# 或源码安装到 ~/.fzf
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install
装完直接运行 fzf,会列出当前目录文件,输入关键字即时过滤,回车输出选中项到 stdout:
fzf # 列出当前目录文件,输入关键字即时过滤,回车输出选中项
# Ctrl-R 调出命令历史(fzf 安装脚本已默认绑定)
# **<TAB> 在任意命令后触发路径补全
三、核心套路:把 fzf 接进日常命令
fzf 真正的生产力来自管道。它读取 stdin、把选中项写到 stdout,于是可以嵌进任意命令链。下面四招覆盖 80% 日常场景,核心套路只有一句话:左边产生列表,中间 fzf 筛选,右边消费结果。把这套”生产—筛选—消费”记熟,你就能给任何原本要手敲的命令加上交互式选择。
vim "$(fzf)"
在仓库里搜内容再定位文件(配合 ripgrep,行号也能当预览):
rg --line-number . | fzf --preview 'bat --color=always {1}' | awk -F: '{print $1}'
用 fd 替代 find 遍历文件,再接 fzf 带高亮预览:
fd --type f | fzf --preview 'bat --color=always {}'
模糊切换 Git 分支,不必背全名:
git branch | fzf | xargs git checkout
四、模糊补全:让 Tab 变成搜索框
fzf 的安装脚本默认接管 ** 触发符:在任意命令的参数位置输入 ** 再按 <TAB>,就会弹出模糊补全列表。这在处理长路径、容器 ID、进程号时尤其顺手,因为你不再需要先用 docker ps 抄 ID 再粘贴。补全的候选来源也是可定制的——比如让 ssh **<TAB> 从 ~/.ssh/config 里挑主机,让 kill -9 **<TAB> 直接列出进程,体验接近一个轻量版的命令面板。
# 输入 vim 后连按 ** 再按 <TAB>
vim **<TAB>
# kill 进程也能补全
kill -9 **<TAB>
如果补全没生效,手动在 shell 配置里 source 这两段(bash/zsh 路径类似):
# 在 ~/.bashrc / ~/.zshrc 启用(install 脚本通常已写入)
source ~/.fzf/shell/completion.bash
source ~/.fzf/shell/key-bindings.bash
五、进阶:预览窗口与交互式脚本
–preview 是 fzf 的灵魂。它右侧开一个预览窗,花括号占位符代表当前选中项,可以跑任意命令——比如用 bat 给文件做语法高亮预览。配合 –multi 还能多选,做成小型交互工具。
fzf --preview 'bat --color=always --style=numbers {}'
写一个交互式删除本地分支的小工具,预览显示每个分支最近一次提交:
git branch --format='%(refname:short)' | fzf --multi --preview 'git log -1 --oneline {}' | xargs -I{} git branch -D {}
更进阶的玩法是 --bind 把按键绑定到动作,例如 --bind 'ctrl-r:reload(command)' 可以在不退出列表的情况下重新拉取数据源,实现”实时刷新”的选择器;change:reload(...) 则能在输入变化时动态重建列表。配合 --preview-window 还能控制预览窗的位置、大小和换行。下面这张表是日常最常用的选项速查:
| –preview | 右侧预览窗口,{} 代表当前项 |
| –multi | 允许多选 |
| –query | 预填初始搜索词 |
| –height | 设置弹窗高度,如 40% |
| –reverse | 列表从顶部开始 |
| –bind | 自定义按键,如 change:reload(…) |
六、与 ripgrep / fd / bat 组成现代 CLI 套装
单独一个 fzf 已经好用,但真正的效率来自组合。fd 负责更快更准的文件遍历,ripgrep 负责内容检索,bat 负责带高亮的预览,fzf 负责交互筛选。三者通过管道串起来,等于在终端里拥有了一个”代码导航器”。如果你用 VS Code 写代码,也可以用 fzf 在编辑器外快速定位要改的文件;在 Docker 容器里排障时,fzf 配合 docker ps 能秒选容器 ID。配合 uv 管理 Python 环境、mise 统一多语言版本,这套现代 CLI 套装能让本地开发效率明显提升。ripgrep 的极速检索更是 fzf 内容筛选的最佳拍档(详见 ripgrep 实战)。值得强调的是,这套组合完全免费、跨平台,且不需要任何守护进程——和那些动辄几百 MB 的 GUI 工具相比,它在远程服务器、容器、CI 环境里同样能直接用,不会因为少了图形界面就罢工。
七、落地检查清单
| 安装方式 | macOS 用 brew,服务器用 apt 或源码 |
| 补全脚本 | 在 .bashrc/.zshrc source completion 与 key-bindings |
| 预览依赖 | 装 bat、fd、ripgrep 才能发挥预览 |
| 远程服务器 | 在常用跳板机也装一份,体验一致 |
| 性能 | 超大仓库用 fd 限定目录,避免 fzf 全量扫 |
八、小结
fzf 本身只有几百 KB,却能把命令行从”靠记忆”变成”靠搜索”。从今天起,把 vim $(fzf)、git branch | fzf、kill -9 **<TAB> 这三招用熟,再逐步接上预览和补全,你的终端效率会肉眼可见地提升。它不替代 IDE,而是补齐 IDE 之外的那块”随手检索”空白——花十分钟装上,之后每一天都在回本。如果你愿意继续深入,官方仓库的 wiki 里还有大量现成配方:模糊 cd、ssh 主机选择、man 页浏览、进程树导航,基本你能想到的”列表里挑一个”的场景,都有人写好可直接抄的片段。把它当成一个”交互式选择原语”,你的脚本和别名也会因此变得更顺手。




