Find in files within Vim

Contents

A useful feature in many text editors is the ability to search for regular expressions in multiple files. Vim has this feature, but it is a little hard to find.

Vim provides these commands for searching files:

:grep

:lgrep

:vimgrep

:lvimgrep

All of these commands can be used to search for a regular expression in whatever files you specify. "grep" and "lgrep" use an external application to perform the search, and are great if you are running Vim on a system with a good file searching utility, if you are accustomed to using an external application for your searches, or if your search is not a complicated one. "vimgrep" and "lvimgrep" are part of Vim, and therefore are good for using on any system, especially if you want to use Vim-style regular expressions in your search. Keep in mind though, that vimgrep can often be slower than grep, which will call an external program to do the dirty work.

These commands all fill a list with the results of their search. "grep" and "vimgrep" fill the "quickfix list", which can be opened with :cw or :copen, and is a list shared between ALL windows. "lgrep" and "lvimgrep" fill the "location list," which is local to the current window, and can be opened with :lw or :lopen. Both of these lists can be used to instantly jump to the matching line in whatever file it occurs in.

Use of grep and lgrep depend on the external application they point to, but use of vimgrep and lvimgrep is as follows:

:vim[grep][!] /{pattern}/[g][j] {file} ...

The 'g' option specifies that all matches for a search will be returned instead of just one per line, and the 'j' option specifies that Vim will not jump to the first match automatically.

For example, to search for the words "house" or "home" in all .txt files in the current directory, use:

In the Windows version of Vim, backslash ('\') characters can be used as path separators, but forward slashes also work, and using '/' allows file paths in these searches to work in Vim under any operating system. This is especially useful if your vimrc file is used on multiple platforms, and you want to write mappings for common searches as below.

You can use a mapping, command, or abbreviation for common searches, like a search for a word under the cursor in all files of the same type in the current directory. This can be especially useful if you have it automatically open the results list as well.

This mapping uses <cword> to get the word under the cursor, and searches for it in the current directory and all subdirectories, opening the quickfix window when done:

Finally, this cabbrev uses CTRL-R CTRL-W to get the word under the cursor, limiting the search to files of the same type using expand("%:e"), and moving the cursor on the command-line to be just before the file list using <C-Left>, so that you can easily specify a different search location. This method is nice because you can either type :lvim<Enter> to perform the default search, or :lvim<Space> to enter the default search into the command line, but leave it there for editing.

Note: Using a cabbrev and a mapping together may not work very well, because the mapping will trigger the cabbrev. Also, be careful not to use common text in your cabbrev, such as making one for the "vim" command, because then whenever you try to edit a .vim file for example, the cabbrev will be expanded when you press Enter. You could avoid this by moving the cursor to somewhere else in the line before pressing enter.

Using vimgrep to search hundreds of files can be slow. A search taking only a few seconds using an external grep program might take nearly a minute with vimgrep. One reason for this is that vimgrep uses Vim's procedures to read files, which can involve execution of several autocommands.

You can make use of the :noautocmd command modifier to significantly increase search speed by temporarily disabling all autocmds during the execution of the :vimgrep. It may also solve other issues you may have, such as unwanted interaction with plugins that trigger off BufRead events. Use it as follows:

This simple addition should work in any of the examples given in this tip, including mappings and abbreviations.

An unfortunate side effect of disabling autocmds in this way is that you may find syntax highlighting is off when Vim displays the result. One workaround is to type :e and press Enter to reload the file. Another is to use the j flag in the search, to prevent jumping to the first match automatically. You will then need to enter a command such as :cw to open the quickfix window, then press Enter to see it. Or, use :cnext.

Note that autocmds must be enabled in order for vimgrep to work for remote or archived files, since Vim's editing of such files depends on plugins using autocmds.

If you want to speed up searching in files, and you don't need the power of Vim's regular expressions or its ability to detect file encodings, you can use an external program (traditionally grep) for searching. But, remember to do it within Vim using :grep, so that you have the output available in Vim to view and navigate by!

Depending on your system, you may find that a command like the following will quickly search files:

One of the advantages of using an external command, is that the search is sometimes much more customizeable than Vim's built-in commands. For example, performing a customized grep search on the word under the cursor:

If you fill file exclude.list with file patterns to exclude from search, such as "*~" – all files ending in a '~' character – the search can be made much faster by virtue of only searching files of interest. See the man pages for grep on your system for details of the oter options.