fzf - 命令行模糊搜索神器

前言

fzf 是一款功能强大的命令行模糊搜索工具。

fzf 可以对文件,命令行历史记录,进程,主机名,标签,git 提交等进行模糊搜索。

fzf 的另一个常见的用处就是以插件形式集成到 Vim 上:fzf.vim

安装

这里简单介绍下源码安装:

git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf 
~/.fzf/install

更多安装方法,请查看:Installation

使用方法

  • 基础使用fzf 默认会启用用户交互查找,从标准输入流(STDIN)读取,并将匹配内容输出到标准输出流(STDOUT)中:
find * -type f | fzf

fzf 如果没有接受标准输入流,那么就会直接进行文件查找(不包含隐藏文件),可以通过设置FZF_DEFAULT_COMMAND修改该默认动作):

fzf # 直接输入 fzf,打开文件搜索功能

:在 fzf 的用户交互界面中,用户的操作有如下动作可选:

  1. 使用CTRL-J/CTRL-K(或者CTRL-N/CTRL-P)进行上下选择
  2. 使用Enter选中条目,CTRL-C/CTRTRL-G/ESC进行退出操作
  3. 在多选择模式(-m),使用TABShift-TAB标记多个条目
  4. Emacs 风格按键绑定
  5. 支持鼠标操作
  • 搜索语法fzf 默认不支持正则搜索,为了操作更加简单直接,通过空格分隔单词,查找匹配所有字符串(无序)。fzf 还提供了一些增强功能的搜索语法,如下表所示:
标记 匹配类型 描述
sbtrkt 模糊匹配 内容匹配sbtrkt(字符匹配)
'wild 精确匹配(单引号) 内容包含单词wild(单词匹配)
^music 前缀精确匹配 music开头
.mp3$ 后缀精确匹配 .mp3结尾
!fire 反转匹配 内容不包含fire
!^music 前缀反转匹配 不以music开头
!.mp3$ 后缀反转匹配 不以.mp3结尾

:如果不想使用模糊匹配或者不想"引用"每个文字,可以使用-e/--exact选项。注意如果使用-e/--exact,那么'就变成了解引用,即:'abc表示匹配a,bca,b,c有序),而不仅仅是匹配abc

  • 或操作fzf 以空格分隔,默认使用的是 与操作(无序),如果想使用 或操作,那么可以使用|
^core go$ | rb$ | py$ # 表示以`core`开头,且以`go`或`rb`或`py`结尾

|前后必须带空格。

  • 模糊补全:在 bash 或 zsh 终端上,可以通过输入**来触发 fzf 对文件/目录的模糊补全(查找),如下例子所示:
# Files under current directory
# - You can select multiple items with TAB key
vim **<TAB>

# Files under parent directory
vim ../**<TAB>

# Files under parent directory that match `fzf`
vim ../fzf**<TAB>

# Files under your home directory
vim ~/**<TAB>


# Directories under current directory (single-selection)
cd **<TAB>

# Directories under ~/github that match `fzf`
cd ~/github/fzf**<TAB>
  • 命令支持:在 bash 上,fzf 的模糊补全功能只对一些预定义的命令集有效(具体命令集:complete | grep _fzf),但是我们也可以为其他命令设置 fzf 模糊补全功能,如下所示:
# 为 rg 增加模糊补全,rg -F "def main(" **<TAB>
complete -F _fzf_path_completion -o default -o bashdefault rg
# 为 tree 增加模糊补全,tree  **<TAB>
complete -F _fzf_dir_completion -o default -o bashdefault tree

按键绑定

fzf 的安装脚本会为 bash,zsh 和 fish 终端设置以下按键绑定:

按键 描述
CTRL-T 命令行打印选中内容
CTRL-R 命令行历史记录搜索,并打印输出
ALT-C 模糊搜索目录,并进入(cd

其他

  • 环境变量:如下表所示:
name description example
FZF_DEFAULT_COMMAND 输入为 tty 时的默认命令 export FZF_DEFAULT_COMMAND='fd --type f'
FZF_DEFAULT_OPTS 设置默认选项 export FZF_DEFAULT_OPTS="--layout=reverse --inline-info"
FZF_CTRL_T_COMMAND 按键映射<CTRL-T>行为设置
FZF_CTRL_T_OPTS 按键映射<CTRL-T>选项设置
FZF_CTRL_R_OPTS 按键映射<CTRL-R>选项设置
FZF_ALT_C_COMMAND 按键映射<CTRL-C>行为设置
FZF_ALT_C_OPTS 按键映射<CTRL-C>选项设置
  • 界面fzf 默认会以全屏方式显示交互界面,可以使用--height选项设置交互界面高度:
vim $(fzf --height 40%)

可以通过设置$FZF_DEFAULT_OPTS变量更改 fzf 默认行为:

# 设置 fzf 默认交互界面大小
export FZF_DEFAULT_OPTS='--height 40%' 
  • 进程 ID 模糊补全:在使用kill命令时,fzf 会自动触发其自动补全功能:
# Can select multiple processes with <TAB> or <Shift-TAB> keys
kill -9 <TAB>
  • 主机名补全:如下例子所示:
ssh **<TAB>
telnet **<TAB>
  • 预览窗口:可以通过提供--preview选项打开预览窗口,并设置响应命令输出到预览窗口上:
# {} is replaced to the single-quoted string of the focused line
fzf --preview 'cat {}' # 预览文件内容
fzf --preview 'rg -F "def main(" -C 3 {}' # 预览 Python 文件 main 函数前后3行代码

高级配置

  • 更改查找引擎:默认情况下,fzf 使用的查找引擎是系统自带的find命令,这里我们可以对其进行更改,换成更高效的查找引擎:
# 使用 rg 进行搜索
export FZF_DEFAULT_COMMAND='rg --files --hidden'
  • 执行外部程序:我们可以通过设置按键映射在 fzf 交互界面直接开启外部进程(executeexecute-silent)运行我们选中的文件:
# 在交互界面选中文件后,按下 F1,直接使用 vim 打开
fzf --bind 'f1:execute(vim {})' 
  • 简化命令:可以通过定义 shell 脚本简化 fzf 命令执行。比如,下面示例定义了一个函数,结合ag实现传参进行模糊搜索,并用 vim 打开:
# fuzzy grep open via ag
vg() {
  local file

  file="$(ag --nobreak --noheading $@ | fzf -0 -1 | awk -F: '{print $1}')"

  if [[ -n $file ]]
  then
     vim $file
  fi
}
  • 自定义全局快捷键触发:像 fzf 其实已经有为我们提供了一些按键映射,比如<CTRL-T>,可以打印出选中文件。现在我们也仿照写一个该功能脚本,全局快捷键设为<CTRL-G><CTRL-O>

1)首先先写目录搜索(fzf)并打印输出功能脚本:

# .bashrc
outputDir() {
    local dir
    dir=$(find ${1:-.} -type d 2> /dev/null | fzf +m)
    echo $dir
}

2)然后进行全局按键映射:

# .bashrc
bind '"\er": redraw-current-line'
bind '"\C-g\C-o": "$(outputDir)\e\C-e\er"'


1)\e\C-eshell-expand-line默认按键绑定,这是最容易的方式进行按键绑定,缺点就是它对于别名(alias)也会同样进行展开。
2)redraw-current-line:在非 tmux 终端上,该选项必须存在,否则无法清除提示。
3)先source .bashrc,然后按快捷键:<CTRL-G><CTRL-O>,运行结果如下:

  • 为预览窗口增加语法高亮:预览窗口支持 ANSI 颜色,因此我们可以为文件内容增加语法高亮。我们借助 bat 这个库来为我们的文本显示语法高亮功能:
    1)首先,安装 bat 库。具体步骤请查看文档。
    2)终端输入以下内容:
fzf --preview '[[ $(file --mime {}) =~ binary ]] &&
                 echo {} is a binary file ||
                 (bat --style=numbers --color=always {} ||
                  highlight -O ansi -l {} ||
                  coderay {} ||
                  rougify {} ||
                  cat {}) 2> /dev/null | head -500'

结果如下:

  • 自定义模糊补全fzf 目前有提供相关 API 供我们自定义模糊补全功能,具体步骤如下:

1)首先自定义一个函数,使用 fzf 提供的 API:_fzf_complete提供补全功能:

# Custom fuzzy completion for "doge" command
#   e.g. doge **<TAB>
_fzf_complete_doge() {
  _fzf_complete "--multi --reverse" "$@" < <(
    echo very
    echo wow
    echo such
    echo doge
  )
}

2)在 bash 中,使用complete指令链接我们的自定义函数:

[ -n "$BASH" ] && complete -F _fzf_complete_doge -o default -o bashdefault doge

3)终端输入:doge **<TAB>,结果如下所示:

更多高级配置,请查看:wiki

总结

虽然好像写了挺多的,其实总结起来主要就 3 个操作:

  • fzf:直接模糊搜索
  • **<TAB>:触发模糊补全
  • 按键映射<CTRL-T><CTRL-R><ALT-C>

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 143,736评论 1 303
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 61,631评论 1 258
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 95,145评论 0 213
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 41,213评论 0 181
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 49,025评论 1 259
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 38,893评论 1 178
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 30,497评论 2 273
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,240评论 0 167
  • 想象着我的养父在大火中拼命挣扎,窒息,最后皮肤化为焦炭。我心中就已经是抑制不住地欢快,这就叫做以其人之道,还治其人...
    爱写小说的胖达阅读 29,114评论 6 235
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 32,596评论 0 213
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,363评论 2 215
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 30,717评论 1 232
  • 白月光回国,霸总把我这个替身辞退。还一脸阴沉的警告我。[不要出现在思思面前, 不然我有一百种方法让你生不如死。]我...
    爱写小说的胖达阅读 24,279评论 0 32
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,183评论 2 214
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 31,629评论 3 209
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,647评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,047评论 0 167
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 33,625评论 2 232
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 33,734评论 2 236

推荐阅读更多精彩内容