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>

参考

推荐阅读更多精彩内容

  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 2,889评论 0 5
  • 原文地址:https://github.com/JuanitoFatas/slime-user-manual#24...
    Nosee123阅读 1,505评论 0 2
  • fzf是目前最快的fuzzy finder。使用golang编写。结合其他工具(比如ag和fasd)可以完成非常多...
    佛心看世界阅读 1,367评论 0 2
  • 我没有靠山,自己就是山!我没有天下,自己打天下!我没有资本,自己赚资本!我弱了,所有困难就强了。我强了,所有阻碍就...
    氧气ya阅读 1,041评论 4 3
  • 贾宝小朋友考试第一天结束,就恐慌地跟我说,妈妈,我完了!我考砸了! 其实我也慌,我镇定地告诉她,没有关系,深呼吸,...
    琴语阅读 88评论 0 0