Vim查找命令:如何列出所有匹配的文件

8

Vim的:find命令只能匹配一个文件。如果匹配到多个文件,它会给出"Too many file names"的提示。

是否有Vim的命令可以使用通配符或正则表达式来查找文件,并允许用户在匹配的文件之间进行导航?


内部命令更好,不要使用插件。 - river
您可以使用globpath()函数获取文件列表。要列出当前工作目录中的所有Python文件::echo globpath(".", "*.py"),然后您可以显示该列表并让用户更具体地选择,或者如果您想要更高级一些,可以让他们选择一个数字来选择哪个文件。另一个要查看的东西是browse confirm e,它是一个文件浏览器;我对它不太熟悉,但可能有类似于您需要的东西。 - scott_fakename
我不知道这个。这似乎不是我个人想要从vim内部完成的事情。你可以在vimscript中编写一些代码,但这对我来说更像是shell的工作。如果我需要类似的功能,我会编写一个外部脚本或程序来完成,然后在vim中调用它。 - scott_fakename
1
我刚刚在谷歌上搜索了一下。尝试输入 :ee 和一个空格),然后按下控制键和字母 d。它会列出当前目录中的所有文件。然后输入一个 shell 通配符(例如 *.py),它会列出所有 .py 文件。输入整个文件名,它就会打开它。 - scott_fakename
:e 命令也会显示“文件名过多”的消息。使用 :next 命令可以记录匹配的文件,并且单独使用 :next 命令可以打开下一个文件。但是我不知道如何显示文件列表以便选择。 - river
显示剩余2条评论
3个回答

18

您似乎将Vim的命令行补全和:find命令本身混淆了。

:find只接受一个单一的文件名(或解析为单一文件名的内容)作为参数,但是允许您完成单个参数的命令行补全会遍历匹配当前模式的path中的所有文件。

这种混淆使您实际想要的内容不明显:

  • 您是否希望:find打开正在匹配您模式的每个文件进行编辑?
  • 还是您需要一个匹配列表以供选择?

前者由于设计原因是不可能的,但是您可以使用:new命令(:help :new):

:new *.foo

当然,后者是可能的。为此,您需要在~/.vimrc中设置至少几个选项:

set wildmenu
set wildmode=list:full

参见 :help wildmode 以了解如何自定义wildmenu的行为。当然,这些设置也适用于其他命令::edit:split:buffer 等等…

几个建议:

set path+=**

让Vim在path中的其他目录下递归查找文件。请注意,**非常贪婪,这意味着Vim将真正地在这些目录下到处寻找,这可能会非常昂贵和缓慢(考虑 node_modules)。与Vim中的许多事物一样,path值应具有上下文依赖性。

set wildignorecase

告诉Vim在自动完成时忽略大小写::find foo将匹配foo.txtFoo.txt

set wildignore=*.foo,*.bar

告诉 Vim 在进行补全时忽略那些文件(可以是目录)。

最后,这里有一堆映射,让我在 Vim 中的生活如此轻松:

" regex completion instead of whole word completion
nnoremap <leader>f :find *
" restrict the matching to files under the directory
" of the current file, recursively
nnoremap <leader>F :find <C-R>=expand('%:p:h').'/**/*'<CR>

" same as the two above but opens the file in an horizontal window
nnoremap <leader>s :sfind *
nnoremap <leader>S :sfind <C-R>=expand('%:p:h').'/**/*'<CR>

" same as the two above but with a vertical window
nnoremap <leader>v :vert sfind *
nnoremap <leader>V :vert sfind <C-R>=expand('%:p:h').'/**/*'<CR>

这是它的外观:

:find


如果不清楚的话...使用建议的'wildmode'和'wildmenu'设置,您现在只需按 <Tab> 键而不是 <Enter> 键即可循环浏览所有匹配项列表,以完成对 :find 命令的搜索。 - Ben

2
findfile函数可以返回一个列表,因此只需要在自定义命令中调用该函数即可。以下是一个快速的一行代码,它将显示从路径中获取的结果列表,并提示您选择其中一个("FF" == 查找文件):
command! -nargs=1 FF let i=1|let mm=findfile(<q-args>, '', -1)|for f in mm| echo i.':'.f|let i+=1 |endfor|let choice=input('FF: ')|exec 'e ' . mm[choice-1]

例子:

:FF socket.h
1:/usr/include/bits/socket.h
2:/usr/include/asm/socket.h
3:/usr/include/asm-generic/socket.h
4:/usr/include/linux/socket.h
5:/usr/include/sys/socket.h
FF: 

输入您想要的数字,然后按回车键。或者只需按回车键即可获取最后一个。


超级有用!但愿这是内置的。 - Gregory Kuhn

1
我使用以下自定义命令在*.g文件中查找所有待办事项,并将它们列在快速修复窗口中。然后我可以通过在快速修复窗口中按Enter来在它们之间跳转。
command! Td noautocmd vimgrep /TODO\|FIXME/j *.g | cw

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