🌸 一个命令行的模糊搜索器

作者:Sec-Labs | 发布时间:

项目地址

https://github.com/junegunn/fzf

fzf 是一个通用的命令行模糊查找器。

6e078b4bd7085536

 

它是一个用于命令行的交互式 Unix 过滤器,可以与任何列表一起使用; 文件、命令历史记录、进程、主机名、书签、git 提交等。

优点

  • 便携,无依赖
  • 快如闪电
  • 最全面的功能集
  • 灵活的布局
  • 包括电池
    • Vim/Neovim 插件、键绑定和模糊自动完成

目录

安装

fzf 项目由以下组件组成:

  • fzf 可执行的
  • fzf-tmux 在 tmux 窗格中启动 fzf 的脚本
  • 外壳扩展
    • 键绑定( CTRL-TCTRL-RALT-C )(bash、zsh、fish)
    • 模糊自动补全 (bash, zsh)
  • Vim/Neovim 插件

如果您不需要额外的东西, 您可以单独 下载 fzf 可执行文件。

使用自制软件

您可以使用 Homebrew (在 macOS 或 Linux 上)安装 fzf。

brew install fzf

# To install useful key bindings and fuzzy completion:
$(brew --prefix)/opt/fzf/install

fzf 也可以 通过 MacPorts 获得: sudo port install fzf

使用混帐

或者,您可以将此存储库“git clone”到任何目录并运行 安装 脚本。

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

使用 Linux 包管理器

包管理器 Linux 发行版 命令
APK Alpine Linux sudo apk add fzf
APT Debian 9+/Ubuntu 19.10+ sudo apt-get install fzf
Conda   conda install -c conda-forge fzf
DNF Fedora sudo dnf install fzf
Nix NixOS, etc. nix-env -iA nixpkgs.fzf
Pacman Arch Linux sudo pacman -S fzf
pkg FreeBSD pkg install fzf
pkgin NetBSD pkgin install fzf
pkg_add Void Linux pkg_add fzf
XBPS openSUSE sudo xbps-install -S fzf
赛珀 开放SUSE sudo zypper install fzf

⚠️ 默认情况下可能不启用键绑定 (CTRL-T / CTRL-R / ALT-C) 和模糊自动完成。

有关详细信息,请参阅包文档。 (例如 apt-cache show fzf

包装状态

视窗

可以在此处 下载适用于 Windows 的预构建二进制文件 。 fzf 也可以通过 ChocolateyScoop 获得:

包管理器 命令
Chocolatey choco install fzf
Scoop scoop install fzf

可以在 wiki 页面 上找到 Windows 上的已知问题和限制。

作为 Vim 插件

如果您使用 vim-plug ,请将此行添加到您的 Vim 配置文件中:

Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }

fzf#install() 确保您拥有最新的二进制文件,但它是可选的,因此如果您使用不支持挂钩的插件管理器,则可以省略它。

有关更多安装选项,请参阅 README-VIM.md

升级 fzf

fzf 正在积极开发中,您可能希望偶尔升级它。 请根据使用的安装方法按照以下说明进行操作。

  • 混帐: cd ~/.fzf && git pull && ./install
  • 酿造: brew update; brew upgrade fzf
  • 麦克波特: sudo port upgrade fzf
  • 巧克力味的: choco upgrade fzf
  • vim插件: :PlugUpdate fzf

建设fzf

参见 BUILD.md

用法

fzf 将启动交互式查找器,从 STDIN 读取列表,并将所选项目写入 STDOUT。

find * -type f | fzf > selected

如果没有 STDIN 管道,fzf 将使用 find 命令获取不包括隐藏文件的文件列表。 (您可以使用覆盖默认命令 FZF_DEFAULT_COMMAND

vim $(fzf)

使用取景器

  • CTRL-K / CTRL-J (或 CTRL-P / CTRL-N )上下移动光标
  • Enter 键选择项目, CTRL-C / CTRL-G / ESC 退出
  • 在多选模式 ( -m ) 上, TABShift-TAB 标记多个项目
  • Emacs 样式键绑定
  • 鼠标:滚动、单击、双击; shift-click 和 shift-scroll 在多选模式下

布局

默认情况下,fzf 以全屏模式启动,但您可以使用 --height 选项使其在光标下方启动。

vim $(fzf --height 40%)

此外,如果您更喜欢“自上而下”布局而不是默认的“自下而上”布局 ,请查看 --reverse 和选项。 --layout

vim $(fzf --height 40% --reverse)

您可以将这些选项添加到, $FZF_DEFAULT_OPTS 以便默认应用它们。 例如,

export FZF_DEFAULT_OPTS='--height 40% --layout=reverse --border'

搜索语法

除非另有说明,否则 fzf 以“扩展搜索模式”启动,您可以在其中输入多个由空格分隔的搜索词。 例如 ^music .mp3$ sbtrkt !fire

代币 比赛类型 描述
sbtrkt 模糊匹配 匹配的项目 sbtrkt
'wild 精确匹配(引用) 项目包括 wild
^music 前缀精确匹配 开头的项目 music
.mp3$ 后缀精确匹配 以结尾的项目 .mp3
!fire 反向精确匹配 不包括的项目 fire
!^music 反向前缀精确匹配 不以以下开头的项目 music
!.mp3$ 反向后缀精确匹配 不以结尾的项目 .mp3

如果您不喜欢模糊匹配并且不希望“引用”每个单词,请使用 -e--exact 选项启动 fzf。 请注意,当 --exact 设置时, ' -prefix “取消引用”该术语。

单个条形字符术语充当 OR 运算符。 例如,以下查询匹配以 、 或 开头 和 结尾 core 的条目 。 go rb py

^core go$ | rb$ | py$

环境变量

  • FZF_DEFAULT_COMMAND
    • 输入为 tty 时使用的默认命令
    • 例如 export FZF_DEFAULT_COMMAND='fd --type f'
    • > ⚠️ 由于要求略有不同,shell 扩展不使用此变量。
      >
      > (例如 改为 CTRL-T 运行、 运行 和 运行 ) $FZF_CTRL_T_COMMAND vim **<tab> _fzf_compgen_path() cd **<tab> _fzf_compgen_dir()
      >
      > 可用选项将在本文档的后面部分进行描述。
  • FZF_DEFAULT_OPTS
    • 默认选项
    • 例如 export FZF_DEFAULT_OPTS="--layout=reverse --inline-info"

选项

有关选项的完整列表,请参见手册页 ( man fzf )。

演示

如果您通过观看视频学习,请查看 @samoshkin 的这个截屏视频以探索 fzf 功能。

例子

fzf-tmux 脚本

fzf-tmux 是一个 bash 脚本,可在 tmux 窗格中打开 fzf。

# usage: fzf-tmux [LAYOUT OPTIONS] [--] [FZF OPTIONS]

# See available options
fzf-tmux --help

# select git branches in horizontal split below (15 lines)
git branch | fzf-tmux -d 15

# select multiple words in vertical split on the left (20% of screen width)
cat /usr/share/dict/words | fzf-tmux -l 20% --multi --reverse

即使你不在 tmux 上,它仍然可以工作,默默地忽略 -[pudlr] 选项,所以你总是可以 fzf-tmux 在你的脚本中使用。

或者,您可以使用 --height HEIGHT[%] 不以全屏模式启动 fzf 的选项。

fzf --height 40%

命令行的键绑定

安装脚本将为 bash、zsh 和 fish 设置以下键绑定。

  • CTRL-T - 将选定的文件和目录粘贴到命令行
    • 设置 FZF_CTRL_T_COMMAND 覆盖默认命令
    • 设置 FZF_CTRL_T_OPTS 为将附加选项传递给 fzf
  • CTRL-R - 将所选命令从历史记录粘贴到命令行
    • 如果您想按时间顺序查看命令,请 CTRL-R 再次按下以切换按相关性排序
    • 设置 FZF_CTRL_R_OPTS 为将附加选项传递给 fzf
  • ALT-C - cd 进入选择的目录
    • 设置 FZF_ALT_C_COMMAND 覆盖默认命令
    • 设置 FZF_ALT_C_OPTS 为将附加选项传递给 fzf

如果您在 tmux 会话中,则可以通过设置 FZF_TMUX_OPTS (例如 -d 40% )在 tmux 拆分窗格或 tmux 弹出窗口中启动 fzf。 请参阅 fzf-tmux --help 可用选项。

可以在 wiki 页面 上找到更多提示。

bash 和 zsh 的模糊补全

文件和目录

如果光标前的单词以触发序列结尾,则可以触发文件和目录的模糊补全,默认为 ** .

  • COMMAND [DIRECTORY/][FUZZY_PATTERN]**<TAB>

# Files under the 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>

进程 ID

为 kill 命令提供了 PID 的模糊补全。

# Can select multiple processes with <TAB> or <Shift-TAB> keys
kill -9 **<TAB>

主机名

对于 ssh 和 telnet 命令,提供了主机名的模糊完成。 这些名称是从 /etc/hosts 和 ~/.ssh/config 中提取的。

ssh **<TAB>
telnet **<TAB>

环境变量/别名

unset **<TAB>
export **<TAB>
unalias **<TAB>

设置

# Use ~~ as the trigger sequence instead of the default **
export FZF_COMPLETION_TRIGGER='~~'

# Options to fzf command
export FZF_COMPLETION_OPTS='--border --info=inline'

# Use fd (https://github.com/sharkdp/fd) instead of the default find
# command for listing path candidates.
# - The first argument to the function ($1) is the base path to start traversal
# - See the source code (completion.{bash,zsh}) for the details.
_fzf_compgen_path() {
  fd --hidden --follow --exclude ".git" . "$1"
}

# Use fd to generate the list for directory completion
_fzf_compgen_dir() {
  fd --type d --hidden --follow --exclude ".git" . "$1"
}

# (EXPERIMENTAL) Advanced customization of fzf options via _fzf_comprun function
# - The first argument to the function is the name of the command.
# - You should make sure to pass the rest of the arguments to fzf.
_fzf_comprun() {
  local command=$1
  shift

  case "$command" in
    cd)           fzf "$@" --preview 'tree -C {} | head -200' ;;
    export|unset) fzf "$@" --preview "eval 'echo \$'{}" ;;
    ssh)          fzf "$@" --preview 'dig {}' ;;
    *)            fzf "$@" ;;
  esac
}

支持的命令

在 bash 上,仅对一组预定义的命令启用模糊完成( complete | grep _fzf 查看列表)。 _fzf_setup_completion 但是您也可以使用辅助函数 为其他命令启用它。

# usage: _fzf_setup_completion path|dir|var|alias|host COMMANDS...
_fzf_setup_completion path ag git kubectl
_fzf_setup_completion dir tree

自定义模糊补全

(自定义完成 API 是实验性的,可能会发生变化)

对于名为 “COMMAND” 的命令,使用helper 定义 _fzf_complete_COMMAND 函数 。 _fzf_complete

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

  • 前面的参数 -- 是 fzf 的选项。
  • 之后 -- ,只需不变地传递原始完成参数 ( "$@" )。
  • 然后,编写一组生成完成候选的命令,并使用流程替换 ( < <(...) ) 将其输出提供给函数。

zsh 将使用命名约定自动获取函数,但在 bash 中,您必须使用 complete 命令手动将函数与命令相关联。

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

如果需要对 fzf 的输出进行后处理,请 _fzf_complete_COMMAND_post 按如下方式定义。

_fzf_complete_foo() {
  _fzf_complete --multi --reverse --header-lines=3 -- "$@" < <(
    ls -al
  )
}

_fzf_complete_foo_post() {
  awk '{print $NF}'
}

[ -n "$BASH" ] && complete -F _fzf_complete_foo -o default -o bashdefault foo

Vim 插件

请参阅 README-VIM.md

高级主题

表现

fzf 很快,而且 越来越快 。 在大多数用例中,性能应该不是问题。 但是,您可能希望了解影响性能的选项。

  • --ansi 告诉 fzf 在输入中提取和解析 ANSI 颜色代码,这会使初始扫描速度变慢。 所以不建议您将其添加到您的 $FZF_DEFAULT_OPTS .
  • --nth 使 fzf 变慢,因为它必须标记每一行。
  • --with-nth 使 fzf 变慢,因为 fzf 必须标记并重新组装每一行。
  • 如果你绝对需要更好的性能,你可以考虑使用 --algo=v1 (默认是 v2 )让 fzf 使用更快的贪心算法。 但是,此算法不能保证找到匹配的最佳顺序,因此不推荐使用。

执行外部程序

execute 您可以在不离开 fzf ( , execute-silent ) 的情况下设置用于启动外部进程的键绑定。

# Press F1 to open the file with less without leaving fzf
# Press CTRL-Y to copy the line to clipboard and aborts fzf (requires pbcopy)
fzf --bind 'f1:execute(less -f {}),ctrl-y:execute-silent(echo {} | pbcopy)+abort'

有关详细信息,请参阅手册页的 KEY BINDINGS 部分。

重新加载候选人名单

通过将动作绑定 reload 到键或事件,您可以使 fzf 动态重新加载候选列表。 有关详细信息, 请参阅 #1750 。

1. 按 CTRL-R 更新进程列表

FZF_DEFAULT_COMMAND='ps -ef' \
  fzf --bind 'ctrl-r:reload(eval "$FZF_DEFAULT_COMMAND")' \
      --header 'Press CTRL-R to reload' --header-lines=1 \
      --height=50% --layout=reverse

2. 按 CTRL-D 或 CTRL-F 在源之间切换

FZF_DEFAULT_COMMAND='find . -type f' \
  fzf --bind 'ctrl-d:reload(find . -type d),ctrl-f:reload(eval "$FZF_DEFAULT_COMMAND")' \
      --height=50% --layout=reverse

3. 交互式 ripgrep 集成

以下示例使用 fzf 作为 ripgrep 的选择器接口。 我们将操作绑定 reloadchange 事件,因此每次您在 fzf 上键入时,ripgrep 进程将使用占位符表达式表示的更新后的查询字符串重新启动 {q} 。 另外请注意,我们使用了 --disabled 选项,因此 fzf 不执行任何二次过滤。

INITIAL_QUERY=""
RG_PREFIX="rg --column --line-number --no-heading --color=always --smart-case "
FZF_DEFAULT_COMMAND="$RG_PREFIX '$INITIAL_QUERY'" \
  fzf --bind "change:reload:$RG_PREFIX {q} || true" \
      --ansi --disabled --query "$INITIAL_QUERY" \
      --height=50% --layout=reverse

如果 ripgrep 没有找到任何匹配项,它将以非零退出状态退出,并且 fzf 将警告您。 为了抑制警告消息,我们 || true 在命令中添加了它,以便它始终以 0 退出。

有关带有预览窗口选项的更完整示例,请参阅 “使用 fzf 作为交互式 Ripgrep 启动器”

预览窗口

设置该 --preview 选项后,fzf 会自动以当前行作为参数启动外部进程,并在拆分窗口中显示结果。 您 $SHELL 用于执行带有 $SHELL -c COMMAND . 可以使用鼠标或自定义键绑定来滚动窗口。

# {} is replaced with the single-quoted string of the focused line
fzf --preview 'cat {}'

预览窗口支持 ANSI 颜色,因此您可以使用任何语法高亮文件内容的程序,例如 BatHighlight

fzf --preview 'bat --style=numbers --color=always --line-range :500 {}'

您可以使用选项自定义预览窗口的大小、位置和边框,以及使用 --preview-window 选项自定义预览窗口的前景色和背景色 --color 。 例如,

fzf --height 40% --layout reverse --info inline --border \
    --preview 'file {}' --preview-window up,1,border-horizontal \
    --color 'fg:#bbccdd,fg+:#ddeeff,bg:#334455,preview-bg:#223344,border:#778899'

有关选项的完整列表,请参见手册页 ( man fzf )。

可以在 此处 找到更高级的示例。


由于 fzf 是通用文本过滤器而不是文件查找器, 因此将 --preview 选项添加到您的 $FZF_DEFAULT_OPTS .

# *********************
# ** DO NOT DO THIS! **
# *********************
export FZF_DEFAULT_OPTS='--preview "bat --style=numbers --color=always --line-range :500 {}"'

# bat doesn't work with any input other than the list of files
ps -ef | fzf
seq 100 | fzf
history | fzf

尖端

尊重 .gitignore

您可以使用 fdripgrepsilver searcher 而不是默认的 find 命令来遍历文件系统,同时尊重 .gitignore .

# Feed the output of fd into fzf
fd --type f --strip-cwd-prefix | fzf

# Setting fd as the default source for fzf
export FZF_DEFAULT_COMMAND='fd --type f --strip-cwd-prefix'

# Now fzf (w/o pipe) will use fd instead of find
fzf

# To apply the command to CTRL-T as well
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"

如果您希望命令跟随符号链接并且不希望它排除隐藏文件,请使用以下命令:

export FZF_DEFAULT_COMMAND='fd --type f --strip-cwd-prefix --hidden --follow --exclude .git'

鱼壳

CTRL-T fish 的键绑定与 bash 和 zsh 的键绑定不同,它将使用命令行上的最后一个标记作为递归搜索的根目录。 例如,点击 CTRL-T 以下命令行的末尾

ls /var/

将列出 . 下的所有文件和目录 /var/

使用自定义 FZF_CTRL_T_COMMAND 时,使用未扩展的 $dir 变量来利用此功能。 $dir 默认为 . 最后一个标记不是有效目录时。 例子:

set -g FZF_CTRL_T_COMMAND "command find -L \$dir -type f 2> /dev/null | sed '1d; s#^\./##'"

 

标签:工具分享, 文件/文本搜索