Subscribe for free with iTunes, Twitter, or RSS (Ogg or Quicktime).

Vimcasts

Search multiple files with :vimgrep

#44

vimgrep is Vim’s built-in command for searching across multiple files. It’s not so fast as external tools like ack and git-grep, but it has its uses. vimgrep uses Vim’s built-in regex engine, so you can reuse the patterns that work with Vim’s standard search command.

Download

OGG 13.2 MB

Quicktime 22.1 MB

Have you ever wished that Vim would report your position as you navigate through search matches? For example, by saying: ‘match 2 out of 5’.

That’s not a feature provided by Vim’s search command, but it is a feature supplied by the quickfix list. We can use the :vimgrep command to populate the quickfix list with search results from the current file:

:vimgrep /{pattern}/ %

The % character is a special symbol, which represents the filepath of the active buffer.

The {pattern} field behaves more or less as you would expect. You can supply any pattern that would work with Vim’s standard search command.

Searching for the last pattern

You can search for the last pattern in your search history by running:

:vimgrep /<C-r>// %

On the command line, <C-r>/ (that is: CTRL-R followed by /) will insert the last search pattern.

Specifiying the set of files for vimgrep to search

When running the vimgrep command, we have to specify at least one file for the command to search inside. We could provide:

  1. one or more filepaths (separated by whitespace)
  2. a wildcard
  3. a backtick expression
  4. the ## symbol, representing the arglist

The first three from this list should look familiar if you’ve watched Vimcast #42 – Populating the arglist.

The special ## symbol is expanded to represent each of the files from the arglist. It’s really handy in this context. Suppose that we wanted to search the same set of files for one pattern, then another pattern, and so on. It would be a drag to have to specify the same set of files again and again:

:vim /pattern1/ `find . -type f`
:vim /pattern2/ `find . -type f`
:vim /pattern3/ `find . -type f`

We can avoid this repetition by populating the arglist with the set of files we want to work with, then using the special symbol ## (double hash) to reference the arglist:

:args `find . -type f`
:vim /pattern1/ ##
:vim /pattern2/ ##
:vim /pattern3/ ##

Not having to think about which files you’re dealing with frees you up to focus on the more interesting part of the vimgrep command: the pattern.

For more ideas on how to specify the set of files for vimgrep to look inside, check out these articles on ack -f and git ls-files.

Navitating the quickfix list

The results from the vimgrep command are collected in the quickfix list. We can traverse them with the following commands:

Ex command unimpaired map effect
:cprev[ious] [q reverse through quickfix list
:cnext ]q advance through quickfix list
:cfirst [Q go to start of quickfix list
:clast ]Q go to end of quickfix list

The square-bracket mappings are not built-in to Vim, but are added by Tim Pope’s unimpaired plugin (which I recommend).

Vimgrep: pros, cons, and alternatives

I reach for vimgrep when I want to use Vim’s built-in regex engine. I love being able to test my regular expression in one buffer using the search command, then use the same pattern without modification to search across the entire project. For me, that convenience is the killer feature of vimgrep.

On the downside, vimgrep isn’t as quick as some of the alternatives out there. If you want to search a large codebase and get results fast, then you’d be better off using an external tool like git-grep, ack or the silver searcher. All of these external tools integrate with the quickfix list, and you can find Vim plugins for each of them:

The downside to using these external tools it that each uses a different regex syntax from Vim’s.

Further reading