Vim Tips Wiki
Register
Advertisement
Tip 1543 Printable Monobook Previous Next

created January 9, 2008 · complexity basic · author Fritzophrenic · version 7.0


Basic use

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 functions 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 line in whatever file the match 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:

:lvim /\<\(house\|home\)\>/gj *.txt
:lw

Tips and Tricks

Old search results

If you would like to view the results of a previous search, the :colder (or :lolder) and :cnewer (or :lnewer) commands will allow you to do this without typing the search again.

Recursive search

You can use ** in the file pattern to search recursively. For example, to search for all lines containing "dostuff()" in all .c files in the parent directory and all its subdirectories, use:

:vimgrep /dostuff()/j ../**/*.c

Path separators

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.

Mappings

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:

map <F4> :execute "vimgrep /" . expand("<cword>") . "/j **" <Bar> cw<CR>

This command based on VimTip483 uses <cword> to get the word under the cursor, but also uses % to limit the search to the current file only:

command GREP :execute 'vimgrep /'.expand('<cword>').'/gj '.expand('%') | copen

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.

cabbrev lvim
      \ lvim /\<lt><C-R><C-W>\>/gj
      \ *<C-R>=(expand("%:e")=="" ? "" : ".".expand("%:e"))<CR>
      \ <Bar> lw
      \ <C-Left><C-Left><C-Left>

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.

Slow searching

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

Here is a suggestion that can reduce a 30-second search to 5 seconds. Define a command, then use :Vimgrep rather than :vimgrep, or replace it entirely with a cabbrev:

command! -nargs=* Vimgrep let s:eikeep=&ei|set ei=all|vimgrep <args>|let &ei=s:eikeep|unlet s:eikeep

You can place the above line in your vimrc. If you want to paste something into your currently running Vim, try this ("s:" has been omitted):

:command! -nargs=* Vimgrep let eikeep=&ei|set ei=all|vimgrep <args>|let &ei=eikeep|unlet eikeep

The command sets the 'eventignore' (or 'ei') option to "all" so that all autocommand events are ignored. See :help 'eventignore'. A defect of this 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, for example:

:Vimgrep /pattern/j *.c

The j flag means that Vim will not jump to the first hit. You will need to enter a command such as :cw, then press Enter, to see it.

Using external programs for fast searches

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:

:grep pattern *.c

See :help :grep, :help 'grepprg', and Search using quickfix to list occurrences for ways to customize this, either to make it work on your system or to do something else entirely! The above example will work on many Unix-based systems (which have grep in the path), and on many Windows systems (where Vim will try to use findstr).

In addition there are plugins to integrate these utilities with Vim:

See also

References

Comments

Advertisement