> [!NOTE] > 本文档由 WeHub 基于上游 README 翻译整理,属于社区翻译,非官方中文文档。 > [English](./README.en.md) · [原始项目](https://github.com/junegunn/fzf) · [上游 README](https://github.com/junegunn/fzf/blob/HEAD/README.md) > 原作者、版权与许可证归属以原始项目及本仓库 LICENSE 文件为准。
fzf - 命令行模糊查找器 构建状态 版本 许可证 贡献者 赞助者 星标
---
fzf 周边

表达对 fzf 的喜爱——T 恤、马克杯和贴纸现已上架!

commitgoods.com/collections/fzf

--- fzf 是一款通用命令行模糊查找器(fuzzy finder)和交互式终端工具包。 无论你是选择文件、浏览命令历史、预览数据、 通过模糊匹配浏览复杂数据集,还是创建自定义菜单和 工作流,fzf 都提供了将 shell 脚本转变为丰富 终端应用所需的构建模块。 亮点 ---------- - **便携** // 以单一二进制文件分发,便于安装 - **快速** // 经过优化,可在毫秒内处理数百万条目 - **可编程** // 事件驱动架构,用于构建自定义终端界面和工作流 - **开箱即用** // 内置与 Bash、Zsh、Fish、Nushell、Vim 和 Neovim 的集成 目录 ----------------- * [安装](#installation) * [使用 Homebrew](#using-homebrew) * [使用 Mise](#using-mise) * [Linux 软件包](#linux-packages) * [Windows 软件包](#windows-packages) * [使用 git](#using-git) * [二进制发行版](#binary-releases) * [配置 shell 集成](#setting-up-shell-integration) * [Vim/Neovim 插件](#vimneovim-plugin) * [升级 fzf](#upgrading-fzf) * [构建 fzf](#building-fzf) * [用法](#usage) * [使用查找器](#using-the-finder) * [显示模式](#display-modes) * [`--height` 模式](#--height-mode) * [`--popup` 模式](#--popup-mode) * [搜索语法](#search-syntax) * [环境变量](#environment-variables) * [自定义外观](#customizing-the-look) * [选项](#options) * [演示](#demo) * [示例](#examples) * [命令行快捷键](#key-bindings-for-command-line) * [模糊补全](#fuzzy-completion) * [文件和目录](#files-and-directories) * [进程 ID](#process-ids) * [主机名](#host-names) * [环境变量 / 别名](#environment-variables--aliases) * [为 bash 和 zsh 自定义模糊补全](#customizing-fuzzy-completion-for-bash-and-zsh) * [自定义 fzf 补全选项](#customizing-fzf-options-for-completion) * [自定义路径和目录的补全来源](#customizing-completion-source-for-paths-and-directories) * [支持的命令(bash)](#supported-commands-bash) * [自定义模糊补全](#custom-fuzzy-completion) * [Fish 的模糊补全](#fuzzy-completion-for-fish) * [Nushell 的模糊补全](#fuzzy-completion-for-nushell) * [Vim 插件](#vim-plugin) * [高级主题](#advanced-topics) * [针对不同输入类型的自定义](#customizing-for-different-types-of-input) * [性能](#performance) * [执行外部程序](#executing-external-programs) * [切换为不同进程](#turning-into-a-different-process) * [重新加载候选列表](#reloading-the-candidate-list) * [1. 按 CTRL-R 更新进程列表](#1-update-the-list-of-processes-by-pressing-ctrl-r) * [2. 按 CTRL-D 或 CTRL-F 在来源之间切换](#2-switch-between-sources-by-pressing-ctrl-d-or-ctrl-f) * [3. 交互式 ripgrep 集成](#3-interactive-ripgrep-integration) * [预览窗口](#preview-window) * [预览图片](#previewing-an-image) * [技巧](#tips) * [遵循 `.gitignore`](#respecting-gitignore) * [Fish shell](#fish-shell) * [fzf 主题游乐场](#fzf-theme-playground) * [相关项目](#related-projects) * [许可证](#license) * [周边商品](#goods) * [赞助者 :heart:](#sponsors-heart) 安装 ------------ ### 使用 Homebrew 你可以使用 [Homebrew](https://brew.sh/)(在 macOS 或 Linux 上)安装 fzf。 ```sh brew install fzf ``` > [!IMPORTANT] > 要配置 shell 集成(快捷键和模糊补全), > 请参阅[下方说明](#setting-up-shell-integration)。 fzf 也可通过 [MacPorts][portfile] 获取:`sudo port install fzf` [portfile]: https://github.com/macports/macports-ports/blob/master/sysutils/fzf/Portfile ### 使用 Mise 你可以使用 [mise](https://github.com/jdx/mise) 安装 fzf。 ```sh mise use -g fzf@latest ``` ### Linux 软件包 | 软件包管理器 | Linux 发行版 | 命令 | | --------------- | ----------------------- | ---------------------------------- | | APK | Alpine Linux | `sudo apk add fzf` | | APT | Debian 9+/Ubuntu 19.10+ | `sudo apt 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 | OpenBSD | `pkg_add fzf` | | Portage | Gentoo | `emerge --ask app-shells/fzf` | | Spack | | `spack install fzf` | | XBPS | Void Linux | `sudo xbps-install -S fzf` | | Zypper | openSUSE | `sudo zypper install fzf` | > [!IMPORTANT] > 要配置 shell 集成(快捷键和模糊补全), > 请参阅[下方说明](#setting-up-shell-integration)。 [![Packaging status](https://repology.org/badge/vertical-allrepos/fzf.svg?columns=3)](https://repology.org/project/fzf/versions) ### Windows 软件包 在 Windows 上,可通过 [Chocolatey][choco]、[Scoop][scoop]、 [Winget][winget] 和 [MSYS2][msys2] 安装 fzf: | 软件包管理器 | 命令 | | --------------- | ------------------------------------- | | Chocolatey | `choco install fzf` | | Scoop | `scoop install fzf` | | Winget | `winget install fzf` | | MSYS2 (pacman) | `pacman -S $MINGW_PACKAGE_PREFIX-fzf` | [choco]: https://chocolatey.org/packages/fzf [scoop]: https://github.com/ScoopInstaller/Main/blob/master/bucket/fzf.json [winget]: https://github.com/microsoft/winget-pkgs/tree/master/manifests/j/junegunn/fzf [msys2]: https://packages.msys2.org/base/mingw-w64-fzf ### 使用 git 或者,你可以将此仓库 "git clone" 到任意目录,然后运行 [安装](https://github.com/junegunn/fzf/blob/master/install) 脚本。 ```sh git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf ~/.fzf/install ``` 安装脚本会向你的 shell 配置文件中添加行,以修改 `$PATH` 并设置 shell 集成。 ### 二进制发布版 你可以从发布页面下载官方的 fzf 二进制文件。 * https://github.com/junegunn/fzf/releases ### 设置 shell 集成 将以下行添加到你的 shell 配置文件中。 * bash ```sh # 设置 fzf 快捷键和模糊补全 eval "$(fzf --bash)" ``` * zsh ```sh # 设置 fzf 快捷键和模糊补全 source <(fzf --zsh) ``` * fish ```fish # 设置 fzf 快捷键 fzf --fish | source ``` * Nushell——Nushell 不支持将内容管道到 `source`,因此安装 脚本会在自动加载目录中生成一个文件。如果你没有使用安装脚本,可以手动设置: ```nu # 生成集成脚本 mkdir ($nu.default-config-dir | path join "autoload") fzf --nushell | save -f ($nu.default-config-dir | path join "autoload" "_fzf_integration.nu") ``` > [!NOTE] > `--bash`、`--zsh`、`--fish` 和 `--nushell` 选项仅适用于 > 较新版本的 fzf。如果你使用较旧版本的 fzf,或希望进行更精细的控制,可以 > 引用 [/shell](/shell) 目录中的各个脚本文件。这些 > 文件的位置可能因你所用的包管理器而异。 > 请参阅包文档以获取更多信息。 > (例如 `apt show fzf`) > [!TIP] > 你可以通过在引用脚本时,将对应的 `*_COMMAND` 变量设为空字符串来禁用 > CTRL-T、CTRL-R 或 ALT-C 快捷键。例如,禁用 CTRL-R 和 ALT-C: > > * bash:`FZF_CTRL_R_COMMAND= FZF_ALT_C_COMMAND= eval "$(fzf --bash)"` > * zsh:`FZF_CTRL_R_COMMAND= FZF_ALT_C_COMMAND= source <(fzf --zsh)` > * fish:`fzf --fish | FZF_CTRL_R_COMMAND= FZF_ALT_C_COMMAND= source` > * nushell:在你的 `env.nu` 中添加: > `$env.FZF_CTRL_R_COMMAND = ""; $env.FZF_ALT_C_COMMAND = ""` > > 在引用脚本之后设置变量将不会生效。 ### Vim/Neovim 插件 如果你使用 [vim-plug](https://github.com/junegunn/vim-plug),),请将以下内容添加到 你的 Vim 配置文件中: ```vim Plug 'junegunn/fzf', { 'do': { -> fzf#install() } } Plug 'junegunn/fzf.vim' ``` * `junegunn/fzf` 提供基础库函数 * `fzf#install()` 确保你拥有最新二进制文件 * `junegunn/fzf.vim` 是[一个独立项目](https://github.com/junegunn/fzf.vim)), 提供各种有用的命令 要了解更多关于 Vim 集成的信息,请参阅 [README-VIM.md](README-VIM.md)。 > [!TIP] > 如果你使用 Neovim 并偏好基于 Lua 的插件,请查看 > [fzf-lua](https://github.com/ibhagwan/fzf-lua).) 升级 fzf ------------- fzf 正在积极开发中,你可能需要时不时地升级它。请根据你使用的安装方式 按照以下说明操作。 - git:`cd ~/.fzf && git pull && ./install` - brew:`brew update; brew upgrade fzf` - macports:`sudo port upgrade fzf` - chocolatey:`choco upgrade fzf` - vim-plug:`:PlugUpdate fzf` 构建 fzf ------------ 请参阅 [BUILD.md](BUILD.md)。 用法 ----- fzf 会启动交互式查找器,从 STDIN 读取列表,并将选中的项目写入 STDOUT。 ```sh find * -type f | fzf > selected ``` 没有 STDIN 管道时,fzf 会遍历当前目录下的文件系统来获取文件列表。 ```sh vim $(fzf) ``` > [!NOTE] > 你可以覆盖默认行为 > * 要么将 `$FZF_DEFAULT_COMMAND` 设置为一个生成所需列表的命令 > * 要么在 `$FZF_DEFAULT_OPTS` 中设置 `--walker`、`--walker-root` 和 `--walker-skip` 选项 > [!WARNING] > 更稳健的解决方案是使用 `xargs`,但我们展示 > 了上述方案,因为它更容易理解 > ```sh > fzf --print0 | xargs -0 -o vim > ``` > [!TIP] > fzf 还能够将自身转换为另一个进程。 > > ```sh > fzf --bind 'enter:become(vim {})' > ``` > > *有关更多信息,请参阅[转换为另一个进程](#turning-into-a-different-process)。* ### 使用查找器 - `CTRL-K` / `CTRL-J`(或 `CTRL-P` / `CTRL-N`)上下移动光标 - `Enter` 键选择项目,`CTRL-C` / `CTRL-G` / `ESC` 退出 - 多选模式(`-m`)下,使用 `TAB` 和 `Shift-TAB` 标记多个项目 - Emacs 风格快捷键 - 鼠标:滚动、单击、双击;多选模式下 shift+单击 和 shift+滚动 ### 显示模式 fzf 默认以全屏模式运行,但也有其他显示模式。 #### `--height` 模式 使用 `--height HEIGHT[%]`,fzf 将在光标下方以指定高度启动。 ```sh fzf --height 40% ``` `reverse` 布局和 `--border` 与此选项搭配效果良好。 ```sh fzf --height 40% --layout reverse --border ``` 在高度前加上 `~`,可以设置最大高度。 ```sh # Will take as few lines as possible to display the list seq 3 | fzf --height ~100% seq 3000 | fzf --height ~100% ``` 高度值可以是负数。 ```sh # Screen height - 3 fzf --height -3 ``` #### `--popup` 模式 使用 `--popup` 选项,fzf 将在弹出窗口中启动 (需要 tmux 3.3+ 或 Zellij 0.44+)。 ```sh # --popup [center|top|bottom|left|right][,SIZE[%]][,SIZE[%][,border-native]] fzf --popup center # Center, 50% width and height fzf --popup 80% # Center, 80% width and height fzf --popup 100%,50% # Center, 100% width and 50% height fzf --popup left,40% # Left, 40% width fzf --popup left,40%,90% # Left, 40% width, 90% height fzf --popup top,40% # Top, 40% height fzf --popup bottom,80%,40% # Bottom, 80% width, 40% height ``` 当你不处于 tmux 或 Zellij 环境中时,`--popup` 会被静默忽略。 > [!NOTE] > 如果你使用的是不支持弹出窗口的旧版 tmux, > 或者你想在常规 tmux 窗格中打开 fzf,请查看 > [fzf-tmux](bin/fzf-tmux) 脚本。 > [!TIP] > 你可以将这些选项添加到 `$FZF_DEFAULT_OPTS` 中,以便默认应用它们。 > 例如, > > ```sh > # 如果在 tmux 或 Zellij 中则在弹出窗口中打开,否则使用 --height 模式 > export FZF_DEFAULT_OPTS='--height 40% --popup bottom,40% --layout reverse --border top' > ``` ### 搜索语法 除非另有指定,fzf 以"扩展搜索模式"启动,你可以输入多个以空格分隔的搜索词。例如 `^music .mp3$ sbtrkt !fire` | 标记 | 匹配类型 | 描述 | | --------- | -------------------------------------- | ------------------------------------------ | | `sbtrkt` | 模糊匹配 | 匹配 `sbtrkt` 的项目 | | `'wild` | 精确匹配(带引号) | 包含 `wild` 的项目 | | `'wild'` | 精确边界匹配(两端均带引号) | 在单词边界处包含 `wild` 的项目 | | `^music` | 前缀精确匹配 | 以 `music` 开头的项目 | | `.mp3$` | 后缀精确匹配 | 以 `.mp3` 结尾的项目 | | `!fire` | 反向精确匹配 | 不包含 `fire` 的项目 | | `!^music` | 反向前缀精确匹配 | 不以 `music` 开头的项目 | | `!.mp3$` | 反向后缀精确匹配 | 不以 `.mp3` 结尾的项目 | 如果你不喜欢模糊匹配且不希望给每个词加引号, 请使用 `-e` 或 `--exact` 选项启动 fzf。注意,当设置了 `--exact` 时,`'` 前缀会"取消引号"该词条。 单个竖线字符词条充当 OR 运算符。例如,以下查询匹配以 `core` 开头 且以 `go`、`rb` 或 `py` 结尾的条目。 ``` ^core go$ | rb$ | py$ ``` ### 环境变量 - `FZF_DEFAULT_COMMAND` - 当输入为 tty 时使用的默认命令 - 例如 `export FZF_DEFAULT_COMMAND='fd --type f'` - `FZF_DEFAULT_OPTS` - 默认选项 - 例如 `export FZF_DEFAULT_OPTS="--layout=reverse --inline-info"` - `FZF_DEFAULT_OPTS_FILE` - 如果你更倾向于在文件中管理默认选项,请将此变量设置为 指向该文件的位置 - 例如 `export FZF_DEFAULT_OPTS_FILE=~/.fzfrc` > [!WARNING] > `FZF_DEFAULT_COMMAND` 未被 shell 集成使用,因为需求略有差异。 > > * `CTRL-T` 运行 `$FZF_CTRL_T_COMMAND` 以获取文件和目录列表 > * `ALT-C` 运行 `$FZF_ALT_C_COMMAND` 以获取目录列表 > * `vim ~/**` 以前缀(`~/`)作为第一个参数运行 `fzf_compgen_path()` > * `cd foo**` 以前缀(`foo`)作为第一个参数运行 `fzf_compgen_dir()` > > 可用选项详见本文档后续内容。 ### 自定义外观 fzf 的用户界面可通过大量配置选项进行完全自定义。如需快速设置,你可以使用 `default`、`full` 或 `minimal` 等样式预设之一,通过 `--style` 选项启动。 ```sh fzf --style full \ --preview 'fzf-preview.sh {}' --bind 'focus:transform-header:file --brief {}' ``` | 预设 | 截图 | | :--- | :--- | | `default` | | | `full` | | | `minimal` | | 以下是一个基于 `full` 预设的示例:
```sh git ls-files | fzf --style full \ --border --padding 1,2 \ --border-label ' Demo ' --input-label ' Input ' --header-label ' File Type ' \ --preview 'fzf-preview.sh {}' \ --bind 'result:transform-list-label: if [[ -z $FZF_QUERY ]]; then echo " $FZF_MATCH_COUNT items " else echo " $FZF_MATCH_COUNT matches for [$FZF_QUERY] " fi ' \ --bind 'focus:transform-preview-label:[[ -n {} ]] && printf " Previewing [%s] " {}' \ --bind 'focus:+transform-header:file --brief {} || echo "No file selected"' \ --bind 'ctrl-r:change-list-label( Reloading the list )+reload(sleep 2; git ls-files)' \ --color 'border:#aaaaaa,label:#cccccc' \ --color 'preview-border:#9999cc,preview-label:#ccccff' \ --color 'list-border:#669966,list-label:#99cc99' \ --color 'input-border:#996666,input-label:#ffcccc' \ --color 'header-border:#6699cc,header-label:#99ccff' ```
### 选项 请查阅手册(`fzf --man` 或 `man fzf`)获取完整选项列表。 ### 演示 如果你喜欢通过视频学习,可以观看 [@samoshkin](https://github.com/samoshkin)) 制作的这个录屏,探索 `fzf` 的各项功能。 示例 -------- * [示例 Wiki 页面](https://github.com/junegunn/fzf/wiki/examples)) * *免责声明:该页面上的示例由社区维护,未经全面测试* * [高级 fzf 示例](https://github.com/junegunn/fzf/blob/master/ADVANCED.md)) 命令行按键绑定 ----------------------------- 通过[设置 shell 集成](#setting-up-shell-integration),你可以在 bash、zsh、fish 和 Nushell 中使用以下按键绑定。 - `CTRL-T` - 将选中的文件和目录粘贴到命令行中 - 列表通过 `--walker file,dir,follow,hidden` 选项生成 - 你可以通过设置 `FZF_CTRL_T_COMMAND` 为自定义命令来覆盖默认行为 - 或者你可以在 `FZF_CTRL_T_OPTS` 中设置 `--walker*` 选项 - 设置 `FZF_CTRL_T_OPTS` 以向 fzf 传递额外选项 ```sh # 使用 bat 预览文件内容(https://github.com/sharkdp/bat)) export FZF_CTRL_T_OPTS=" --walker-skip .git,node_modules,target --preview 'bat -n --color=always {}' --bind 'ctrl-/:change-preview-window(down|hidden|)'" ``` - 可以通过在加载脚本时将 `FZF_CTRL_T_COMMAND` 设为空字符串来禁用 - `CTRL-R` - 将选中的历史命令粘贴到命令行中。 - 使用 `TAB` 选择多条命令。 - 如果想按时间顺序查看命令,再次按下 `CTRL-R` 可切换为按相关性排序 - 按下 `ALT-R` 切换"原始"模式,可查看匹配项周围的上下文。在该模式下,按下 `CTRL-N` 和 `CTRL-P` 仅在匹配项之间移动。 - 按下 `CTRL-/` 或 `ALT-/` 切换自动换行 - 按下 `SHIFT-DELETE` 删除选中的命令(bash 和 fish) - 仅限 Fish shell: - 按下 `ALT-ENTER` 重新格式化并插入选中的命令 - 按下 `ALT-T` 循环切换命令前缀(时间戳、日期/时间、无) - 设置 `FZF_CTRL_R_OPTS` 以向 fzf 传递额外选项 ```sh # CTRL-Y 使用 pbcopy 将命令复制到剪贴板 export FZF_CTRL_R_OPTS=" --bind 'ctrl-y:execute-silent(echo -n {2..} | pbcopy)+abort' --color header:italic --header 'Press CTRL-Y to copy command into clipboard'" ``` ```fish # Fish shell:设置日期/时间为默认前缀 set -gx FZF_CTRL_R_OPTS "--with-nth 1,3.. --bind 'alt-t:change-with-nth(2..|3..|1,3..)'" # 或默认不显示前缀 set -gx FZF_CTRL_R_OPTS "--with-nth 3.. --bind 'alt-t:change-with-nth(2..|1,3..|3..)'" ``` - 可以通过在加载脚本时将 `FZF_CTRL_R_COMMAND` 设为空字符串来禁用 - 通过非空的 `FZF_CTRL_R_COMMAND` 进行自定义覆盖暂不支持,会发出警告 - `ALT-C` - 进入选中的目录 - 列表通过 `--walker dir,follow,hidden` 选项生成 - 设置 `FZF_ALT_C_COMMAND` 以覆盖默认命令 - 或者你可以在 `FZF_ALT_C_OPTS` 中设置 `--walker-*` 选项 - 设置 `FZF_ALT_C_OPTS` 以向 fzf 传递额外选项 ```sh # 在预览窗口中打印树形结构 export FZF_ALT_C_OPTS=" --walker-skip .git,node_modules,target --preview 'tree -C {}'" ``` - 可以通过在加载脚本时将 `FZF_ALT_C_COMMAND` 设为空字符串来禁用 这些绑定的显示模式可通过 `FZF_{CTRL_T,CTRL_R,ALT_C}_OPTS` 单独配置,或通过 `FZF_DEFAULT_OPTS` 全局配置。 (例如:`FZF_CTRL_R_OPTS='--popup bottom,60% --height 60% --border top'`) 更多技巧请参见 [Wiki 页面](https://github.com/junegunn/fzf/wiki/Configuring-shell-key-bindings).) 模糊补全 ---------------- Shell 集成还为 bash、zsh、fish 和 Nushell 提供了模糊补全功能。 ### 文件和目录 如果光标前的单词以触发序列结尾(默认为 `**`),则可触发文件和目录的模糊补全。 - `COMMAND [DIRECTORY/][FUZZY_PATTERN]**` ```sh # Files under the current directory # - You can select multiple items with TAB key vim ** # Files under parent directory vim ../** # Files under parent directory that match `fzf` vim ../fzf** # Files under your home directory vim ~/** # Directories under current directory (single-selection) cd ** # Directories under ~/github that match `fzf` cd ~/github/fzf** ``` ### 进程 ID 为 kill 命令提供了 PID 的模糊补全。 ```sh # Can select multiple processes with or keys kill -9 ** ``` ### 主机名 为 ssh 命令提供了主机名的模糊补全。主机名从 /etc/hosts 和 ~/.ssh/config 中提取。 ```sh ssh ** ``` ### 环境变量 / 别名 ```sh # bash and zsh unset ** export ** unalias ** # fish set ``` ### 自定义 bash 和 zsh 的模糊补全 #### 自定义补全的 fzf 选项 ```sh # Use ~~ as the trigger sequence instead of the default ** export FZF_COMPLETION_TRIGGER='~~' # Options to fzf command export FZF_COMPLETION_OPTS='--border --info=inline' # Options for path completion (e.g. vim **) export FZF_COMPLETION_PATH_OPTS='--walker file,dir,follow,hidden' # Options for directory completion (e.g. cd **) export FZF_COMPLETION_DIR_OPTS='--walker dir,follow' # 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 --preview 'bat -n --color=always {}' "$@" ;; esac } ``` #### 自定义路径和目录的补全来源 ```sh # Use fd (https://github.com/sharkdp/fd) 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" } ``` #### 支持的命令(bash) 在 bash 中,模糊补全仅对预定义的命令集生效 (可通过 ``complete | grep _fzf`` 查看列表)。但你也可以使用 ``_fzf_setup_completion`` 辅助函数为其他命令启用模糊补全。 ```sh # usage: _fzf_setup_completion path|dir|var|alias|host COMMANDS... _fzf_setup_completion path ag git kubectl _fzf_setup_completion dir tree ``` #### 自定义模糊补全 _**(自定义补全 API 处于实验阶段,可能发生变更)**_ 对于名为 _"COMMAND"_ 的命令,使用 ``_fzf_complete`` 辅助函数定义 ``_fzf_complete_COMMAND`` 函数。 ```sh # Custom fuzzy completion for "doge" command # e.g. doge ** _fzf_complete_doge() { _fzf_complete --multi --reverse --prompt="doge> " -- "$@" < <( echo very echo wow echo such echo doge ) } ``` - ``--`` 之前的参数是传递给 fzf 的选项。 - ``--`` 之后,只需原封不动地传递原始的补全参数(``"$@"``)。 - 然后,编写一组命令来生成补全候选,并通过进程替换(``< <(...)``) 将其输出送入该函数。 zsh 会根据命名约定自动识别该函数,但在 bash 中,你需要使用 ``complete`` 命令手动将函数与命令关联。 ```sh [ -n "$BASH" ] && complete -F _fzf_complete_doge -o default -o bashdefault doge ``` 如果你需要对 fzf 的输出进行后处理,可以按如下方式定义 ``_fzf_complete_COMMAND_post``。 ```sh _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 ``` ### Fish 的模糊补全 Fish 的模糊补全与 bash 和 zsh 的区别在于: - 它不需要像 ``**`` 这样的触发序列。相反,它在 ``Shift-TAB`` 上激活(替代原生分页器搜索模式),而 ``TAB`` 保留 fish 的原生补全行为。 - 它依赖 fish 的原生补全系统来生成候选列表,而非执行递归的文件系统遍历。如需递归搜索, 请改用 ``CTRL-T`` 绑定。 - 如果当前命令行令牌是通配符模式,它会在通配符展开路径列表上执行搜索(而非将 所有结果插入命令行的原生行为)。由于展开由 shell 执行,结果数量存在上限。 - 仅支持的配置变量是 ``FZF_COMPLETION_OPTS`` 和 ``FZF_EXPANSION_OPS``。 - 自定义补全函数所使用的函数名为 ``fzf_complete``,它只接受 fzf 选项作为参数,也可以在没有任何重定向输入的情况下调用, 仅用于修改 fzf 选项同时呈现原生补全结果。为了与其他 shell 兼容, 提供了名为 ``_fzf_complete`` 的函数,它在 fzf 选项之后可以接受命令行参数中的 `` -- $argv``。 对于 fish 补全覆盖不到的命令,最好创建常规的 fish 补全函数(这对 ``TAB`` 和 ``Shift-TAB`` 都有效),并仅在需要修改特定命令的 fzf 选项或希望 ``Shift-TAB`` 获得不同结果时才创建 fzf 补全函数: ```fish # Customize git completion function _fzf_complete_git # Show header text with active branch for all git completions set -lx -- FZF_COMPLETION_OPTS --header="'"(git branch --show-current 2>/dev/null)"'" # No other changes when less than 3 arguments, or when completing options if not set -q argv[3]; or string match -q -- '-*' $argv[-1] fzf_complete return end # Check subcommand switch $argv[2] case checkout diff log show # Set preview and display all branches and commits for subcommands: checkout, diff, log, show begin git branch --all --format='%(refname:short)' git log --all --oneline --color=always end | fzf_complete --no-multi --ansi --accept-nth=1 --query=$argv[-1] --preview='git show --color=always {1}' case add rm mv # Only set preview for subcommands: add, rm, mv # Special characters in fish completion lists are escaped, so the r flag must be used. fzf_complete --preview="git diff --color=always {r1}" case '*' # No changes for other subcommands fzf_complete end end ``` 与 bash 和 zsh 类似,可以通过定义一个名为 ``_fzf_complete_COMMAND_post`` 或 ``_fzf_post_complete_COMMAND`` 的函数来对 fzf 的输出进行处理后再插入命令行: ```fish function _fzf_complete_foo ls -sh --zero --color=always | fzf_complete --read0 --print0 --ansi --no-multi-line --header-lines=1 end function _fzf_post_complete_foo while read -lz result string escape -n -- $result | string trim -l -c '\ ' | string split -m 1 -f 2 ' ' end end ``` ### Nushell 的模糊补全 Nushell 中的模糊补全通过 [外部补全器](https://www.nushell.sh/cookbook/external_completers.html)) 机制实现。与 bash 和 zsh 相比存在一些差异: - 在 Nushell >= 0.103.0 上,内置命令(例如 ``cd``、``ls``)不再调用外部补全器。使用 ``**`` 的模糊补全仅对外部命令生效。 - 自定义补全器可以通过 ``$env.FZF_COMPLETERS`` 记录在你的 ``config.nu`` 中定义。每个条目是一个闭包,接收前缀和命令跨度,返回候选字符串列表或包含自定义 fzf 选项的记录 ``{ candidates: [...], opts: [...] }``: ```nu $env.FZF_COMPLETERS = { pacman: {|prefix, spans| let sub = $spans | skip 1 | first let candidates = (if ($sub =~ "-[SF]") { ^pacman -Slq | lines } else if ($sub =~ "-[QR]") { ^pacman -Qq | lines } else { [] }) { candidates: $candidates, opts: ["--preview", "pacman -Si {}"] } } } ``` 更多示例请参见 [shell/completion-examples.nu](shell/completion-examples.nu)。 - 支持以下环境变量: ``FZF_COMPLETION_TRIGGER``、``FZF_COMPLETION_OPTS``、 ``FZF_COMPLETION_PATH_OPTS``、``FZF_COMPLETION_DIR_OPTS``、 ``FZF_COMPLETION_DIR_COMMANDS``。 Vim 插件 ---------- 参见 [README-VIM.md](README-VIM.md)。 高级主题 --------------- ### 针对不同类型输入的自定义 由于 fzf 是一个通用的文本过滤器,其算法设计为"一般"能很好地适用于任何类型的输入。但不可否认,没有真正通用的解决方案,你可能需要根据输入类型调整算法和一些设置。为简化这一过程,fzf 为几种常见输入类型提供了一套"方案"。 | 方案 | 描述 | | :--- | :--- | | ``--scheme=default`` | 通用方案,设计为能很好地适用于任何类型的输入 | | ``--scheme=path`` | 适用于文件路径 | | ``--scheme=history`` | 适用于命令历史或任何按时间顺序排列重要的输入 | (详见 ``fzf --man``) ### 性能 fzf 很快。在大多数使用场景中性能不应成为问题。不过,你可能需要注意那些会影响性能的选项。 - ``--ansi`` 告知 fzf 提取并解析输入中的 ANSI 颜色代码,这会使初始扫描变慢。因此不建议将其加入 ``$FZF_DEFAULT_OPTS``。 - ``--nth`` 会使 fzf 变慢,因为它需要对每一行进行分词。 - 纯字符串 ``--delimiter`` 应优先于正则表达式分隔符。 - ``--with-nth`` 会使 fzf 变慢,因为它需要对每一行进行分词并重新组装。 ### 执行外部程序 你可以设置按键绑定,在不离开 fzf 的情况下启动外部进程(``execute``、``execute-silent``)。 ````bash # 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' ```` 详情请参阅手册的*按键/事件绑定*章节。 ### 切换为另一个进程 ``become(...)`` 与上文介绍的 ``execute(...)``/``execute-silent(...)`` 类似,不同之处在于它不会执行命令后返回 fzf,而是将 fzf 切换为执行该命令的新进程。 ````sh fzf --bind 'enter:become(vim {})' ```` 与看似等效的命令替换 ``vim "$(fzf)"`` 相比,这种方式有几个优势: * 当用 CTRL-C 终止 fzf 时,Vim 不会打开空文件 * 当在空结果上按 ENTER 时,Vim 不会打开空文件 * 可以处理多项选择,即使其中包含空格 ```sh fzf --multi --bind 'enter:become(vim {+})' ``` 公平地说,使用 ``fzf --print0 | xargs -0 -o vim`` 代替 ``vim "$(fzf)"`` 可以解决上述所有问题。尽管如此,``become(...)`` 在不同场景下仍提供了额外优势。 * 你可以设置多个绑定,以不同方式处理结果,而无需任何包装脚本 ```sh fzf --bind 'enter:become(vim {}),ctrl-e:become(emacs {})' ``` * 之前,你需要使用 ``--expect=ctrl-e`` 并检查 fzf 输出的第一行 * 你可以利用 fzf 的字段索引表达式轻松构建后续命令 ```sh # 在 Vim 中打开文件并跳转到指定行 git grep --line-number . | fzf --delimiter : --nth 3.. --bind 'enter:become(vim {1} +{2})' ``` ### 重新加载候选列表 通过将 ``reload`` 操作绑定到某个按键或事件,你可以让 fzf 动态重新加载候选列表。详情请参见 `https://github.com/junegunn/fzf/issues/1750`。 #### 1. 按 CTRL-R 更新进程列表 ````sh ps -ef | fzf --bind 'ctrl-r:reload(ps -ef)' \ --header 'Press CTRL-R to reload' --header-lines=1 \ --height=50% --layout=reverse ```` #### 2. 按 CTRL-D 或 CTRL-F 切换源 ````sh 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 的选择器界面。我们将 ``reload`` 操作绑定到 ``change`` 事件,这样每当你在 fzf 中输入时,ripgrep 进程都会重新启动,并使用占位符表达式 ``{q}`` 表示更新后的查询字符串。另外,注意我们使用了 ``--disabled`` 选项,使 fzf 不执行任何二次过滤。 ````sh : | rg_prefix='rg --column --line-number --no-heading --color=always --smart-case' \ fzf --bind 'start:reload:$rg_prefix ""' \ --bind 'change:reload:$rg_prefix {q} || true' \ --bind 'enter:become(vim {1} +{2})' \ --ansi --disabled \ --height=50% --layout=reverse ```` 如果 ripgrep 没有找到任何匹配项,它将以非零退出码退出,fzf 会对此发出警告。要抑制该警告信息,我们为命令添加了 ``|| true``,使其始终以 0 退出。 更复杂的示例请参见 ["Using fzf as interactive Ripgrep launcher"](`https://github.com/junegunn/fzf/blob/master/ADVANCED.md#using-fzf-as-interactive-ripgrep-launcher)`)。 ### 预览窗口 设置 ``--preview`` 选项后,fzf 会自动启动一个外部进程,将当前行作为参数传入,并在拆分窗口中显示结果。你的 ``$SHELL`` 用于执行该命令,``$SHELL -c COMMAND`` 作为参数传入。可以使用鼠标或自定义按键绑定来滚动窗口。 ````bash # {} is replaced with the single-quoted string of the focused line fzf --preview 'cat {}' ```` 预览窗口支持 ANSI 颜色,因此你可以使用任何能够对文件内容进行语法高亮的程序,例如 [Bat](`https://github.com/sharkdp/bat)`) 或 [Highlight](`https://gitlab.com/saalen/highlight):`)。 ````bash fzf --preview 'bat --color=always {}' --preview-window '~3' ```` 你可以使用 ``--preview-window`` 选项自定义预览窗口的大小、位置和边框,使用 ``--color`` 选项自定义其前景色和背景色。例如: ````bash fzf --height 40% --layout reverse --info inline --border \ --preview 'file {}' --preview-window up,1,border-horizontal \ --bind 'ctrl-/:change-preview-window(50%|hidden|)' \ --color 'fg:#bbccdd,fg+:#ddeeff,bg:#334455,preview-bg:#223344,border:#778899' ```` 完整选项列表请参阅手册(``man fzf``)。 更多高级示例请参见[此处](`https://github.com/junegunn/fzf/blob/master/ADVANCED.md).`)。 > [!WARNING] > 由于 fzf 是通用文本过滤器而非文件查找器,**不建议将 ``--preview`` 选项加入你的 ``$FZF_DEFAULT_OPTS``**。 > > ```sh > # ********************* > # ** 不要这样做!** > # ********************* > export FZF_DEFAULT_OPTS='--preview "bat --style=numbers --color=always --line-range :500 {}"' > > # bat 不适用于除文件列表以外的任何输入 > ps -ef | fzf > seq 100 | fzf > history | fzf > ``` ### 预览图片 fzf 可以通过以下协议之一在预览窗口中显示图片: * [Kitty 图形协议](`https://sw.kovidgoyal.net/kitty/graphics-protocol/)`) * [iTerm2 内联图片协议](`https://iterm2.com/documentation-images.html)`) * [Sixel](`https://en.wikipedia.org/wiki/Sixel)`) 更多信息请参见 [bin/fzf-preview.sh](bin/fzf-preview.sh) 脚本。 ````sh fzf --preview 'fzf-preview.sh {}' ```` 技巧 ---- ### 遵守 ``.gitignore`` 你可以使用 [fd](`https://github.com/sharkdp/fd),`)、[ripgrep](`https://github.com/BurntSushi/ripgrep),`) 或 [The Silver Searcher](`https://github.com/ggreer/the_silver_searcher)`) 来遍历文件系统,同时遵守 ``.gitignore``。 ````sh # 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 the fd command to generate the list fzf # To apply the command to CTRL-T as well export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND" ```` 如果你希望命令跟随符号链接且不排除隐藏文件,请使用以下命令: ````sh export FZF_DEFAULT_COMMAND='fd --type f --strip-cwd-prefix --hidden --follow --exclude .git' ```` ### Fish shell 与 bash 和 zsh 不同,fish 的 ``CTRL-T`` 按键绑定会将命令行上的最后一个 token 作为递归搜索的根目录。例如,在以下命令行的末尾按下 ``CTRL-T``: ````sh ls /var/ ```` 将列出 ``/var/`` 下的所有文件和目录。 使用自定义 ``FZF_CTRL_T_COMMAND`` 时,请使用未展开的 ``$dir`` 变量来利用此功能。当最后一个 token 不是有效目录时,``$dir`` 默认为 ``.``。示例: ````sh set -g FZF_CTRL_T_COMMAND "command find -L \$dir -type f 2> /dev/null | sed '1d; s#^\./##'" ```` ### fzf 主题游乐场 [fzf 主题游乐场](`https://vitormv.github.io/fzf-themes/)`) 由 [Vitor Mello](`https://github.com/vitormv)`) 创建,是一个可以交互式创建 fzf 主题的网页。 相关项目 -------- `https://github.com/junegunn/fzf/wiki/Related-projects` [License](LICENSE) ------------------ MIT 许可证 (MIT) Copyright (c) 2013-2026 Junegunn Choi Goods ----- 在此获取 fzf T 恤、马克杯和贴纸:https://commitgoods.com/collections/fzf Sponsors :heart: ---------------- 我要感谢本项目的所有赞助商,是他们让我能够继续改进 fzf。 如果你想赞助本项目,请访问 https://github.com/sponsors/junegunn.