今天在闲逛博客 的时候偶然发现 crispgm 所写的文章,其中推荐了 fzf 这款模糊搜寻工具,所以立马上手体验了一下。
fzf 是一个通用的命令行模糊搜索工具,用 golang 编写,大家的评价都是目前最快的 fuzzy finder,配合 ag 的使用,依靠模糊的关键词,可以快速定位文件。配合一些脚本,可以完全颠覆以前使用命令行的工作方式。
Installation
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install
or upgrade
cd ~/.fzf && git pull && ./install
Demo
最直接的使用方式就是在终端输入:
fzf
或者 fzf 可以接受 stdin,比如使用命令
find * -type f | fzf
此时会进入 fzf 的交互窗口,在交互窗口中可以使用 Ctrl + n 或者 Ctrl + p 来上下移动光标。使用 Enter 选中条目
其他常用:
- Ctrl-j Ctrl-n 都能往下,不过 Ctrl-j 在我的配置中是切换到下 pane 所以我只用 Ctrl-n
- Ctrl-k Ctrl-p 都能往上,不过 Ctrl-k 在我的配置中是切换到上 pane 所以我只用 Ctrl-p
- Ctrl-c 或者 Ctrl-g 或者 Ctrl-q 或者 Esc 用来退出 abort
- Ctrl-h 退格键 backspace,不过这个键和 tmux vim 有冲突所以一般不用
- Ctrl-a 光标跳转到开头 Ctrl-e 跳转到行结尾
- Ctrl-w 向前删以 word
- Ctrl-u 删除所有输入
其实看到后面就发现很多快捷键其实是和 Bash/Shell 下一致的,其他更多的交互命令,可以参考 man fzf
Configuration
FZF_DEFAULT_COMMAND
fzf 默认查找文件使用的是系统的 find
命令,你可以通过自定义该环境变量来更改使用其他命令比如 ag 或者 fd
# 这行配置开启 ag 查找隐藏文件 及忽略 .git 文件
export FZF_DEFAULT_COMMAND='ag --hidden --ignore .git -l -g ""'
# or
export FZF_DEFAULT_COMMAND="fd --exclude={.git,.idea,.sass-cache,node_modules,build} --type f"
FZF_DEFAULT_OPTS
该环境变量定义了 fzf 的参数:
export FZF_DEFAULT_OPTS="--height 40% --layout=reverse --preview '(highlight -O ansi {} || cat {}) 2> /dev/null | head -500'"
常见的一些操作
fzf 最最常用的快捷键应该就是 Ctrl + r 和 Ctrl + t 了。Ctrl-r 用来在历史中搜索,Ctrl-t 用来搜索当前文件夹下的内容。
历史记录搜索
在没有使用 fzf 之前都是 Ctrl + r 来快速输入历史命令,用起来倒也没有太大的问题,fzf 使得 Ctrl-r 变得更加好用,按下 Ctrl-r 之后立即就能够显示之前的历史命令,通过模糊搜索能够展示一个列表,从列表中选择即可。
历史命令 Ctrl-r
在终端命令行下按下 Ctrl-r 会列出 history 命令目录,选中 Enter 离开 fzf 后,该条目会拷贝到命令行中。
搜索当前文件夹 Ctrl-t
在命令行中按下 Ctrl-t 会打开 fzf 窗口,此时如果找到某文件,并选择 Enter,那么该文件名会被拷贝到命令行中。比如说想要打开某文件但是忘记了名字,那么可以先输入 vi
然后按下 Ctrl-t 那么会出现 fzf 的搜索窗口,在窗口中可以模糊搜索文件,然后将文件路径及文件拷贝到命令行中。
同样的方式,如果要 mv
一个文件,同样先输入 mv
然后再 Ctrl-t 找到文件,继续输入目的地址即可。
如果想要更简单 fzf GitHub wiki 中展示了非常多的 Bash Shell 的配置 1,比如可以定义命令 fe
fe() {
local files
IFS=$'\n' files=($(fzf-tmux --query="$1" --multi --select-1 --exit-0))
[[ -n "$files" ]] && ${EDITOR:-vim} "${files[@]}"
}
那么在 shell 中直接输入 fe
然后回车会自动出现当前目录的 fzf,选择文件之后回车即可用默认 $EDITOR
打开文件。
多选
假如在 fzf 选择窗口中想要选择多个文件,那么可以使用 tab
来进行多选,使用 Ctrl-n, Ctrl-p 上下切换的时候,可以使用 Tab 来选中期望的文件进行多选操作。
比如移动,删除,或者编辑多个文件时可以使用。
更改路径
在 fzf 之前最原始的方法就是 cd 然后输入一个词,不断的按 Tab 直到完整的输入 Path,回车。但假如 path 比较长,那么可能需要费一些时间找到真正想要去的目录,而如果用 fzf 配置
fd() {
local dir
dir=$(find ${1:-.} -path '*/\.*' -prune \
-o -type d -print 2> /dev/null | fzf +m) &&
cd "$dir"
}
在终端输入 fd
然后搜索一下目录回车就能直接到该目录下,效率提升 x 倍。
Kill Process
再比如说 fkill
用来 kill process
# fkill - kill process
fkill() {
local pid
pid=$(ps -ef | sed 1d | fzf -m | awk '{print $2}')
if [ "x$pid" != "x" ]
then
echo $pid | xargs kill -${1:-9}
fi
}
Tmux
再比如创建 Tmux session 一般都是 tmux new -s new-session
创建,如果使用 tmuxinator 则可能 mux name
比较快,但是如果在 fzf 这里只需要 tm new-session
# tm - create new tmux session, or switch to existing one. Works from within tmux too. (@bag-man)
# `tm` will allow you to select your tmux session via fzf.
# `tm irc` will attach to the irc session (if it exists), else it will create it.
tm() {
[[ -n "$TMUX" ]] && change="switch-client" || change="attach-session"
if [ $1 ]; then
tmux $change -t "$1" 2>/dev/null || (tmux new-session -d -s $1 && tmux $change -t "$1"); return
fi
session=$(tmux list-sessions -F "#{session_name}" 2>/dev/null | fzf --exit-0) && tmux $change -t "$session" || echo "No sessions found."
}
如果 session 不存在则会自动创建,使用 fs 可以快速选择目前可用的 session.
# fs [FUZZY PATTERN] - Select selected tmux session
# - Bypass fuzzy finder if there's only one match (--select-1)
# - Exit if there's no match (--exit-0)
fs() {
local session
session=$(tmux list-sessions -F "#{session_name}" | \
fzf --query="$1" --select-1 --exit-0) &&
tmux switch-client -t "$session"
}
Alt-c
命令行中按下 Alt-c,会列出当前文件夹下的目录,选择后会直接进入该文件夹。
搜索语法
在上面一系列的基础操作后,对 fzf 应该有了一定的了解,那么知道 fzf 的搜索语法其实非常强大,在熟悉正则的基础上,用 fzf 搜索语法可以实现很多的组合,比如使用 !
来表示不包含,比如 !word
不包含 word
的结果。
比如:
^music
以 music 开头mp3$
以 mp3 结尾'word
严格匹配!word
不包含 word!.mp3$
不以.mp3
结尾
等等,可以在官方网站上看到。
扩展阅读
一些比较高效的搜索工具