起因
终端里"找东西"老操作:
cd ../../../some/path—— 路径长 + 容易记错Ctrl-R反向搜历史 —— 一次只能展示一条git checkout <Tab>—— 分支多了 tab 全列出来kill <pid>—— 先ps查 PID 再 kill
fzf 给所有这些场景加了模糊搜索 + 实时筛选 + 多选。装一次,所有地方
都香。
装
# macOS
brew install fzf
$(brew --prefix)/opt/fzf/install # 装 shell 集成
# Ubuntu/Debian
apt install fzf
# 或者源码(最新版)
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install
install 脚本问你装不装 Ctrl-T(粘文件)/Ctrl-R(搜历史)/Alt-C
(cd 目录)键绑定 → 全选 yes。
基础体验
shell 里随便敲:
$ fzf
打开一个全屏列表(默认是当前目录所有文件),上下选 / 输入字符模糊
过滤 / 回车确认。
$ vim $(fzf) # 模糊找文件然后 vim 打开
$ cat $(fzf)
必装的 shell 绑定
Ctrl-T # 触发"插入文件路径"模式(任何 cmd 后都能用)
Ctrl-R # 反向搜命令历史,模糊匹配
Alt-C # cd 到模糊选中的子目录
例:
$ git diff <Ctrl-T> # 弹列表选文件 → 插入路径
$ vim <Ctrl-T> # 同上
Ctrl-R 把内建反搜替换成多行筛选,找老命令快 10 倍。
与 ripgrep / fd 配合
fd(rust find)+ rg(ripgrep)+ fzf 三件套:
# ~/.zshrc
export FZF_DEFAULT_COMMAND='fd --type f --hidden --exclude .git'
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"
export FZF_ALT_C_COMMAND='fd --type d --hidden --exclude .git'
Ctrl-T 只列文件 + 隐藏文件 + 排除 .git,速度起飞(fd 比 find 10x 快)。
实战 alias
# kill 进程 with fzf
alias fkill='ps -ef | fzf --multi | awk "{print \$2}" | xargs kill'
# git checkout 分支模糊选
gco() {
local branch=$(git branch --all | grep -v HEAD | sed 's/^..//' | fzf)
git checkout "$branch"
}
# cd 到最近用过的目录
cdh() {
local dir=$(dirs -p | uniq | fzf)
cd "$dir"
}
# kubectl pod fzf
kpod() {
kubectl get pods --all-namespaces | fzf
}
# tmux session 切换
tms() {
local session=$(tmux ls -F '#{session_name}' | fzf)
tmux switch-client -t "$session"
}
每条都是日常高频,5 个字符内启动 + 模糊选 + 操作。
preview 窗口
最强 feature:右侧实时显示选中项预览。
fzf --preview 'cat {}'
# 文件用 bat(高亮)
fzf --preview 'bat --color=always {}' --preview-window right:60%
# git log fzf
git log --oneline | fzf --preview 'git show --color {1}'
# JSON file 用 jq
fzf --preview 'jq -C . {}'
{} 是 placeholder 选中项。{1} 是第一字段(空格分割)。
多选
--multi / -m 模式,Tab 选 / Shift-Tab 反选。
# 选多个文件 git add
git add $(git status --short | awk '{print $2}' | fzf -m)
# 选多个 PR 关闭
gh pr list | fzf -m | awk '{print $1}' | xargs -I{} gh pr close {}
fzf 嵌入工具
很多 CLI 把 fzf 当 picker:
forgit:git 操作 + fzf 选 hunk / commitfz:autojump 替代,fzf 选历史目录peco:fzf 的另一选择(go 写)sk(skim):rust 写的 fzf 兼容
fzf as filter(programmable)
不只是交互工具,也是 Unix filter:
echo -e "apple\nbanana\norange" | fzf # 交互选
echo -e "apple\nbanana\norange" | fzf -f "ap" # 非交互过滤
echo -e "apple\nbanana\norange" | fzf -f "ap" --print-query
--filter/-f 非交互模式,可以塞 pipeline。
tmux 集成
fzf-tmux -p 70%,70% # 在 tmux popup 里跑 fzf
不会污染当前窗口。tmux 3.2+ 才有 popup 支持。
性能
fzf 是 Go 写的,单线程能扫几百万行(typical < 100ms)。
benchmark:
| 文件数 | 启动时间 |
|---|---|
| 10k | 30ms |
| 100k | 100ms |
| 1M | 800ms |
100w 文件项目(monorepo)也 sub-second。
与替代品对比
- peco(go):同代,UI 略不同,更新少
- sk / skim(rust):兼容 fzf,速度更快,preview 略弱
- selecta(ruby):老 + 慢,过时
fzf 仍是事实标准。
我的 .zshrc 完整片段
# fzf
[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
export FZF_DEFAULT_COMMAND='fd --type f --hidden --exclude .git'
export FZF_DEFAULT_OPTS='--height 50% --layout=reverse --border --preview-window right:50%'
export FZF_CTRL_T_OPTS="--preview 'bat --color=always --line-range :100 {}'"
export FZF_ALT_C_OPTS="--preview 'eza --tree --color=always {} | head -50'"
export FZF_CTRL_R_OPTS="--preview 'echo {}' --preview-window down:3:wrap"
# alias
alias gco='git_checkout_fzf'
alias gst='git_status_fzf'
git_checkout_fzf() {
git branch --all --color=always | grep -v HEAD | \
fzf --ansi --preview 'git log --color {-1} -10 --oneline' | \
sed 's/.* //' | xargs git checkout
}
踩过的坑
-
shell 启动慢:fzf 装多个集成 → zsh 启动 +200ms。
time zsh -i -c exit测一下,找 culprit。 -
Ctrl-R跟其它工具冲突:tmux / vim / readline 都用 Ctrl-R。
fzf 集成默认覆盖 bash/zsh 的内建,要小心副作用。 -
fd在 Debian 名字是fdfind:装时apt install fd-find→
命令叫fdfind。alias 一下alias fd=fdfind。 -
preview 卡:preview 命令慢(如 git show 大 commit)→ fzf 看着卡。
--preview-window noborder+ 优化 preview 命令。 -
macOS 与 zsh 5.9 兼容:老 zsh 可能 fzf widget 报错。升 zsh / brew
upgrade zsh。
登录后参与评论。