vimtricks.wiki Concise Vim tricks, one at a time.

How do I search for a pattern across multiple files and navigate the results?

Answer

:vimgrep /pattern/ **/*.ext | copen

Explanation

The :vimgrep command searches for a regex pattern across multiple files and populates the quickfix list with every match. Combined with :copen, you get an interactive results window that lets you jump between matches across your entire project — all without leaving Vim.

How it works

  • :vimgrep /pattern/ **/*.ext recursively searches all files matching the glob for the given pattern
  • ** means recursive descent into subdirectories
  • *.ext is a file glob — use **/*.py, **/*.js, **/* etc.
  • | copen chains the quickfix window open immediately after the search completes
  • Each entry in the quickfix list shows the file, line number, and matching text

Example

Find every TODO comment in your JavaScript project:

:vimgrep /TODO/ **/*.js | copen

The quickfix window opens at the bottom:

src/app.js|12| // TODO: add error handling
src/utils.js|45| // TODO: refactor this function
tests/helper.js|8| // TODO: add more test cases

Press <CR> on any line to jump to that match. Use :cnext and :cprev to step through results without returning to the quickfix window.

Tips

  • Use :cn (:cnext) and :cp (:cprev) to step forward and backward through results
  • :cfirst and :clast jump to the first and last match
  • Use :cdo s/old/new/g | update to run a substitution on every matched line across all files
  • Use :cfdo %s/old/new/g | update to run the substitution on every matched file instead
  • Add j to suppress the automatic jump to the first match: :vimgrep /pattern/j **/*.py
  • For faster searches on large codebases, use :grep with an external tool like rg (ripgrep): :set grepprg=rg\ --vimgrep then :grep pattern
  • The quickfix list persists until replaced — use :colder and :cnewer to navigate between previous quickfix lists
  • Use :lvimgrep for a per-window location list instead of the global quickfix list

Next

How do I edit multiple lines at once using multiple cursors in Vim?