Найти файл (с помощью рекурсивного поиска по каталогам) в Vim


84

Есть ли способ рекурсивного поиска файла в каталоге (при необходимости с использованием подстановочных знаков) в Vim? Если не изначально, есть ли плагин, который может с этим справиться?




@CiroSantilli 巴拿馬 文件 六四 事件 法轮功 Я имею в виду ваше имя ... которое выражает нечто запрещенное в Китае.
E_Jovi

1
@E_Jovi, а что значит 吊? Просто чтобы улучшить мой китайский язык :-)
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

2
@CiroSantilli 巴拿馬 文件 六四 事件 法轮功 Как рекомендательный термин, это означает, что вы делаете что-то, в то время как большинство других людей не могут; в этом случае я думаю, что ваше имя говорит правду об истории, но большинство китайцев не могут этого сделать из-за поведения правительства как уничижительный термин, он выражает то, что человек говорит или ведет себя таким образом, который демонстрирует неуважение к человеку.
E_Jovi

Ответы:


110

В команде можно использовать подстановочные знаки :edit. Так,

:e **/test/Suite.java

откроет test / Suite.java независимо от того, где он находится в текущей иерархии каталогов. Это работает с завершением табуляции, поэтому вы можете использовать [tab] для раскрытия подстановочных знаков перед открытием файла. См. Также параметр wildmode, чтобы вместо этого просмотреть все возможные расширения.

Еще одна уловка - использовать

:r! find . -type f

для загрузки списка всех файлов в текущем каталоге в буфер. Затем вы можете использовать все обычные инструменты редактирования текста vim для навигации / сортировки / обрезки списка, а также CTRL+W gfдля открытия файла под курсором в новой панели.


1
+1 Я никогда не пробовал использовать подстановочный знак в команде редактирования. Это очень хорошо работает и с диким режимом. Итак, вы можете набрать: e ** / Suite <tab>, и у всех будет список возможных файлов
mb14,

7
Будьте очень осторожны с большими коллекциями файлов со сложной структурой каталогов. Эта команда может повесить ваш vim на очень долгое время. С моей кодовой базой он искал уже 20 минут. Дело усложняет то, что это невозможно остановить. Я пробовал обычные Ctrl + C и Ctrl + Break. Procmon показывает, что vim все еще ищет мой файл. Так что решение не для всех :(
evpo

1
@evpo У меня была такая же проблема. Я решил это, указав первую часть пути в поиске, чтобы уменьшить количество папок: e dir / ** / File.java. Дальше прошло меньше секунды.
user79878 05

1
как, черт возьми, я не знал об этом? Пользуюсь vim более 20 лет. Просто потрясающе 👏🏼👏🏼👏🏼
Брэдли

1
ОМГ, ЭТО УДИВИТЕЛЬНО!
Funkodebat

51

Есть команда поиска. Если вы добавите **(см. :help starstar) В свой, 'path'вы можете рекурсивно искать:

:set path

покажет вам ваш текущий путь, добавьте **, выполнив что-то вроде

:set path+=**

тогда вы можете просто ввести

:find myfile.txt

и открывается волшебно!

Если вы добавите команду set в свой .vimrc, она обеспечит вам возможность выполнять рекурсивный поиск в будущем. Кажется, он не ищет точечные каталоги (например, .ssh)


1
Если имя файла очень длинное, этот метод не очень удобен, или он my*.txtтакже подходит ?
Шрикант Шарат

1
Да, вы можете использовать подстановочный знак *. см :h find.
Tae

12
Вы также можете добавить к своему пути, выполнив:set path+=**
alanboy

есть ли опасность добавить подобную логику к vimrc? cc @alanboy
iamnotsam

21

Я бы рекомендовал ctrlp.vim . Это очень хороший плагин, идеально подходящий для работы внутри больших проектов. В нем есть поиск по имени файла или полному пути, поиск по регулярному выражению, автоматическое определение корня проекта (тот, который находится в папке .git | hg | svn | bzr | _darcs), персонализированные исключения имен файлов и многое другое.

Просто нажмите, <c-p>и откроется очень интуитивно понятная панель, где вы можете искать то, что хотите:

введите описание изображения здесь

Можно выбрать и открыть сразу несколько файлов. Он также принимает дополнительные произвольные команды, такие как переход к определенной строке, вхождение строки или любую другую команду Vim.

Репо: https://github.com/kien/ctrlp.vim


5
kien / ctrlp.vim кажется неподдерживаемым. Похоже, существует консенсус в отношении использования вилки ctrlpvim / ctrlp.vim, которая, похоже, активно поддерживается: github.com/ctrlpvim/ctrlp.vim
Дэмиен Безбородов

4
fzf очень похож на ctrlp. Это быстрее и лучше сортирует результаты. Он также работает вне Vim, но имеет отличную встроенную поддержку Vim: github.com/junegunn/fzf
still_dreaming_1

6

vim как встроенную команду поиска (: help find), но открывать только первый найденный файл. Однако вы можете использовать этот замечательный плагин: FuzzyFinder, который делает все, что вы хотите, и даже больше.


3

Вы можете просматривать файловую систему с помощью :ex ., но я не знаю, как выполнять рекурсивный поиск (я новичок в Vim - я использую его всего десять лет).

Есть несколько популярных плагинов файловых браузеров:

См. Также эту ветку на SuperUser .


3

Command-T позволяет очень быстро найти файл, просто набрав несколько букв. Вы также можете открыть файл в новой вкладке, но для этого потребуется vim, скомпилированный с поддержкой ruby.


И ctrlp.vim тоже.
Крис


1

vim имеет билд в командах grep, lgrep, vimgrep или lvimgrep, которые могут это делать

вот руководство о том, как их использовать http://vim.wikia.com/wiki/Find_in_files_within_Vim#Recursive_Search

вы также можете использовать внешнюю команду, например find или grep, из vim, выполнив ее следующим образом

:!find ...

Как это могут сделать grep, lgrep, vimgrep или lvimgrep? Они ищут файл, а не файл.
kroiz

например, используя: grep test * / .java
Николаус Градвол

не будет ли это искать слово test в именах файлов .java? Не могли бы вы объяснить? Я не мог заставить его работать.
kroiz

@kroiz, да :grep test */.javaбудет искать слово testво всех .javaфайлах. :!findбудет использовать команду findоболочки для поиска файлов. Команда findоболочки довольно мощная, если объединить ее с pcre или расширенным регулярным выражением
alpha_989 04

1

Я удивлен, что никто еще не упомянул Unite.vim .

Поиск файлов (нечеткий или иной) - это лишь верхушка айсберга того, что он может сделать для разработчика. Он имеет встроенную поддержку ag, gitи множество других программ / утилит / VIM плагин. Кривая обучения может быть немного крутой, но я не могу представить свою жизнь без нее. База пользователей большая, и ошибки исправляются сразу.


1

Просмотр результатов в стиле Quickfix

Применение:

Find my.regex

Итог:

  • открывается новая вкладка
  • каждая строка содержит относительный путь, соответствующий grep -Eрегулярному выражению
  • ударил:
    • <enter>или <C-w>gfоткрыть файл в текущей строке в новой вкладке
    • gf открыть файл на текущей вкладке и потерять список файлов

Вместо этого найдите все файлы:

Find

Альтернативные методы:

  • Gfind my.regex: искать только файлы, отслеживаемые Git ( git ls-files). Скрытый запрос: https://github.com/tpope/vim-fugitive/issues/132#issuecomment-200749743
  • Gtfind my.regex: нравится Gfind, но искать из верхнего уровня git, а не из текущего каталога
  • Locate somefile: locateверсия

Код:

function! Find(cmd)
  let l:files = system(a:cmd)
  if (l:files =~ '^\s*$')
    echomsg 'No matching files.'
    return
  endif
  tabedit
  set filetype=filelist
      set buftype=nofile
  " TODO cannot open two such file lists with this. How to get a nice tab label then?
  " http://superuser.com/questions/715928/vim-change-label-for-specific-tab
  "file [filelist]
  put =l:files
  normal ggdd
  nnoremap <buffer> <Enter> <C-W>gf
  execute 'autocmd BufEnter <buffer> lcd ' . getcwd()
endfunction
command! -nargs=1 Find call Find("find . -iname '*'" . shellescape('<args>') . "'*'")
command! -nargs=1 Gfind call Find('git ls-files | grep -E ' . shellescape('<args>'))
command! -nargs=1 Gtfind call Find('git rev-parse --show-toplevel && git ls-files | grep -E ' . shellescape('<args>'))
command! -nargs=1 Locate call Find('locate ' . shellescape('<args>'))

1

В зависимости от вашей ситуации (то есть при условии, что следующая команда найдет только один файл), возможно, используйте такую ​​команду, как:

:e `locate SomeUniqueFileName.java`

Это заставит Vim открыть на текущей вкладке (команда e) файл, который является результатом выполнения (в этом примере),

locate SomeUniqueFileName.java

Обратите внимание, что волшебство здесь - это обратные кавычки вокруг команды, которые преобразуют вывод команды оболочки в текст, который можно использовать в команде Vim.


1

Вам не нужен плагин только для этой функции, достаточно фрагмента кода ниже.

function! FindFiles()
    call inputsave()
    let l:dir = input("Find file in: ", expand("%:p:h"), "dir")
    call inputrestore()
    if l:dir != ""
        call inputsave()
        let l:file = input("File name: ")
        call inputrestore()
        let l:nf = 'find '.l:dir.' -type f -iname '.l:file.' -exec grep -nH -m 1 ".*" {} \;'
        lexpr system(l:nf)
    endif
endfunction
nnoremap <silent> <leader>fo :call FindFiles()<CR>

Пожалуйста, добавьте пример, как его использовать.
Виталий Зданевич

1

Бежать:

:args `find . -name '*xml'`

Vim выполнит команду оболочки с обратными кавычками, поместит список файлов в список arglist и откроет первый файл. Затем вы можете использовать его :argsдля просмотра списка arglist (т.е. списка найденных файлов) :nи :Nдля перехода вперед и назад по файлам в списке arglist. См. Https://vimhelp.org/editing.txt.html#%7Barglist%7D и https://vimhelp.org/editing.txt.html#backtick-expansion.


0

С помощью этого плагина вы можете рекурсивно находить файлы по своему «пути» . Он также поддерживает завершение табуляции для имени файла.


0

Инструмент ag и соответствующий плагин Ag vim отлично решают эту проблему:

Чтобы найти файл по шаблону, используйте:

AgFile! pattern

Откроется окно быстрого исправления с результатами, в которых вы можете выбрать.

Вы можете добавить привязку клавиш vim для вызова этой команды, используя выбранное слово в качестве шаблона.

nnoremap <silent> <C-h> :AgFile! '<C-R><C-W>'<CR>
vnoremap <silent> <C-h> y :AgFile! '<C-R>"'<CR>
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.