如何从不同于当前工作目录的目录中启动fzf?

12

我经常使用 fzf 来浏览文件系统,特别是 Alt-c 快捷键。

当调用时,fzf 会从当前工作目录生成一个列表。

是否可以让 fzf 从指定的目录生成一个列表?

我尝试过 fzf <dir>,但它会导致错误(未知选项)。另外,我找不到任何像 -C <dir> 这样用于指定起始目录的选项。


请在[su]上提问。[so]专注于编程问题。 - user1934428
4个回答

7

我有一个更普遍的问题,可能对您有用。以下内容来自我写的一篇博客文章

配置FZF以搜索除了工作目录之外的有用目录

我既使用fzf作为命令行工具,也使用fzf.vim插件在Vim中使用它。它可以直观、快速地查找(和打开)文件,并使您无需记住其位置或确切名称。默认情况下,fzf会在当前目录内递归搜索,这通常就是您想要的。如果您需要在当前工作目录之外的某个目录中搜索文件,则需要将该路径指定为fzf的参数,之后就像往常一样(fzf将递归搜索指定的目录)。

问题

总感觉有时必须精确指定路径才能进行模糊搜索...精确指定路径正是fzf应该解放您的负担的问题!我的初始方法是提供主目录路径并让fzf搜索所有内容,主目录路径只需要几个字符即可指定,所以在这种情况下没有实质性的负担。

这样做的问题是你最终会搜索很多你知道没有你想要的文件的目录。主要问题是一些额外安装例如anaconda3创建的目录,这时结果会被数以千计的内部文件淹没,路径非常长。长路径往往会“吸收”搜索中输入的任何字母,因此很难被fzf过滤掉。

解决方案

您可以选择fzf在幕后使用哪种搜索工具。默认值为标准的Linux find命令,但也可以使用fd、ripgrep或silver searcher。除了比默认的find快得多之外,这些后续工具还尊重 .ignore 文件。这意味着fzf将跳过列在.ignore文件中的任何文件或目录。我们可以将此功能转化为我们的优势。

首先,我们需要安装fd。如果您使用的是Ubuntu 19.04(Disco Dingo)或更新版本,则可以安装官方维护的软件包:

sudo apt install fd-find

如果你使用的是较旧版本的Ubuntu,你可以从发布页面下载最新的.deb软件包,并通过以下方式进行安装:
# adapt version number and architecture
sudo dpkg -i fd_8.2.1_amd64.deb

现在我们通过在 .bashrc 文件中添加以下行来配置 fzf 使用 fd:
export FZF_DEFAULT_COMMAND="fdfind . $HOME"

如果您使用的是 Ubuntu 19.10 之前的旧版本,则需要对上述行进行修改,如下所示:
export FZF_DEFAULT_COMMAND="fd . $HOME"

fzf现在将始终从主目录递归搜索,并遵守任何.ignore文件。因此,让我们在主目录中创建一个:

touch ~/.ignore

我发现,我可能需要递归搜索的目录列表(大约15个)比我永远不想搜索的目录列表更短。我希望搜索的目录中的文件总数大约为5000个左右 - 可以轻松处理fd。
在.ignore文件中,我首先列出了所有的主目录,每个目录后跟着一个'/':
# start by igoring every home directory
anaconda3/
arch/
cache/
code/
Desktop/
  .
  .
  .

接下来,在这些行以下,放置你希望进行搜索的目录列表,每个目录前面需要加上 '!' ,并以斜杠 '/' 结尾:

# now un-ignore the ones I care about
!code/
!Desktop/
!documents/
!downloads/
  .
  .
  .

'!'将“取消”之前的忽略命令。
这样我们就可以在文件系统的任何位置调用fzf,开始键入与我们想要查找的文件相关的模糊信息,fzf将在一组预定义的目录中搜索,并轻松找到它。这完全消除了思考文件可能位于何处以及它的确切名称的障碍。
注意:我注意到,由于某种原因,一些子目录在fzf搜索中没有显示出来,因此我在本节中显式创建了一些“!path/to/missed/directory/”行...
注意:您可能会想知道“如果我发现自己处于不在列表中的不寻常目录中,并且想要使用fzf怎么办?”我有同样的担忧,所以我在我的.bashrc中放置了一些别名,可以随意切换上述配置(对于Ubuntu 19.10+,请务必使用'fdfind',如上所述)。
# restore fzf default options ('fzf clear')
alias fzfcl="export FZF_DEFAULT_COMMAND='fd .'"

# reinstate fzf custom options ('fzf-' as in 'cd -' as in 'back to where I was')
alias fzf-="export FZF_DEFAULT_COMMAND='fd . $HOME'"

如果你使用Vim创建.ignore文件,获取主目录下所有目录的列表的简单方法如下命令:

:.!ls ~/

在列表中的第一个目录上放置光标并输入以下命令,将斜杠'/'添加到所有行结尾:

:.,$ norm A/

与上述类似,将光标放在列表中的第一个目录上,并输入以下命令,在每个目录前插入'!':
:.,$ norm I!

5
你可以像这样做:
  • find <dir> | fzf
  • fd . <dir> | fzf

来源


4
假设您正在使用bash或类似的东西,这已经内置于默认的完成选项中,这些选项与fzf一起安装: https://github.com/junegunn/fzf#fuzzy-completion-for-bash-and-zsh 简而言之; 输入起始文件或目录,添加**并按Tab。因此,如果您输入cd /foo/**,则Tab会打开以/foo为起始目录的fzf。
编辑:在撰写本文时,此操作适用的命令已硬编码在fzf的bash助手中,因此对于catcd有效,但对于tacnano无效。以下是完整列表:
awk cat diff diff3
emacs emacsclient ex file ftp g++ gcc gvim head hg java
javac ld less more mvim nvim patch perl python ruby
sed sftp sort source tail tee uniq vi view vim wc xdg-open
basename bunzip2 bzip2 chmod chown curl cp dirname du
find git grep gunzip gzip hg jar
ln ls mv open rm rsync scp
svn tar unzip zip

如果您想添加其他命令,请在您的.bashrc中使用以下命令,并在fzf被调用的地方之后(类似于[ -f ~/.fzf.bash ] && source ~/.fzf.bash)进行添加:

__fzf_defc "tac" _fzf_path_completion "-o default -o bashdefault"

或者:打开一个问题,询问您想要默认添加到fzf的命令,例如tac和nano非常常见。


不错,我没想到那个!这对哪些命令有效?它适用于 cat,但不适用于 tac - Shuzheng
我一直认为它适用于所有情况(这也是文档 COMMAND [DIRECTORY/][FUZZY_PATTERN]**<TAB> 所暗示的)。所以如果不行,我会说那是个 bug。或者是我们没有正确理解其目的 :) - stijn

0
mattb's 解决方案非常出色!
使用下面的函数,您可以忽略使用 fzfcl/fzf- 设置行为,并直接将路径作为参数提供给 fzf:
fzf () {
    fzf_binary=$(unset -f fzf && which fzf)
    # is path provided
    if [[ "$1" != "" && -d $1 ]]
    then
            export FZF_DEFAULT_COMMAND="fd . $1"
    else
            export FZF_DEFAULT_COMMAND='fd . $HOME'
    fi
    $fzf_binary
}

例如,如果你想让fzf在特定的目录中进行搜索,你可以执行以下命令:
# current dir
fzf .
# or another dir:
fzf <path>

当没有提供参数时,它将根据.ignore规则在$HOME目录中执行。
# this executes in $HOME:
fzf

免责声明: 如果在其他可能调用此函数的工具/脚本中使用fzf,将fzf名称覆盖为该函数可能不是一个好主意。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接