Vim Tips Wiki
(merging/referencing related tips (note tip 438 was already referenced in this tip))
(Add info from vim_use mailing list on slow searches + minor tweaks)
Line 8: Line 8:
 
|version=7.0
 
|version=7.0
 
}}
 
}}
==Basic Use==
+
==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.
 
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 doing this:
+
Vim provides these functions for searching files:
 
*grep
 
*grep
 
*lgrep
 
*lgrep
Line 36: Line 36:
   
 
==Tips and Tricks==
 
==Tips and Tricks==
===Recursive Search===
+
===Recursive search===
 
You can use <tt>**</tt> 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:
 
You can use <tt>**</tt> 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:
 
<pre>
 
<pre>
Line 42: Line 42:
 
</pre>
 
</pre>
   
===Path Separators===
+
===Path separators===
In the Windows version of Vim, backslash ('\') characters can be used as path separators, but 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.
+
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===
 
===Mappings===
Line 50: Line 50:
 
This mapping uses <tt><cword></tt> to get the word under the cursor, and searches for it in the current directory and all subdirectories, opening the quickfix window when done:
 
This mapping uses <tt><cword></tt> to get the word under the cursor, and searches for it in the current directory and all subdirectories, opening the quickfix window when done:
 
<pre>
 
<pre>
map <f4> :execute "vimgrep /" . expand("<cword>") . "/j **" <Bar> cw<CR>
+
map <F4> :execute "vimgrep /" . expand("<cword>") . "/j **" <Bar> cw<CR>
 
</pre>
 
</pre>
   
Line 66: Line 66:
 
\ <C-Left><C-Left><C-Left>
 
\ <C-Left><C-Left><C-Left>
 
</pre>
 
</pre>
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.
 
   
 
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.
==See Also==
 
  +
  +
==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 <tt>:Vimgrep</tt> rather than <tt>:vimgrep</tt>:
  +
  +
<pre>
  +
command! -nargs=* Vimgrep let s:eikeep=&ei|set ei=all|vimgrep <args>|let &ei=s:eikeep|unlet s:eikeep
  +
</pre>
  +
  +
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):
  +
  +
<pre>
  +
:command! -nargs=* Vimgrep let eikeep=&ei|set ei=all|vimgrep <args>|let &ei=eikeep|unlet eikeep
  +
</pre>
  +
  +
The command sets the <tt>'eventignore'</tt> (or <tt>'ei'</tt>) 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 <tt>:e</tt> and press Enter to reload the file. Another is to use the <tt>j</tt> flag in the search, for example:
  +
  +
<pre>
  +
:Vimgrep /pattern/j *.c
  +
</pre>
  +
  +
The <tt>j</tt> flag means that Vim will not jump to the first hit. You will need to enter a command such as <tt>:cw</tt>, 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 <tt>grep</tt>) for searching.
  +
  +
Depending on your system, you may find that a command like the following will quickly search files:
  +
  +
<pre>
  +
:grep pattern *.c
  +
</pre>
  +
  +
See {{help|:grep}}, {{help|'grepprg'}} and [[VimTip483|Search using quickfix to list occurrences]]. The above example will work on many Unix-based systems (which have <tt>grep</tt> in the path), and on many Windows systems (where Vim will try to use <tt>findstr</tt>).
  +
  +
In addition there are plugins to integrate these utilities with Vim:
  +
*{{script|id=311|text=grep.vim : Grep search tools integration with Vim}}
  +
*{{script|id=1575|text=findstr.vim : Using MS-Windows findstr utility to search for text with Vim}}
  +
 
==See also==
 
*[[VimTip1234|Tip 1234: Find files in subdirectories]], for when the contents of a file are not known, but the file name or part of the file name is.
 
*[[VimTip1234|Tip 1234: Find files in subdirectories]], for when the contents of a file are not known, but the file name or part of the file name is.
 
*[[VimTip1008|Tip 1008: Toggle to open or close the quickfix window]], for a quick way to toggle on or off the quickfix window which contains the results of your vimgrep searches.
 
*[[VimTip1008|Tip 1008: Toggle to open or close the quickfix window]], for a quick way to toggle on or off the quickfix window which contains the results of your vimgrep searches.
Line 85: Line 124:
   
 
----
 
----
 
 
[[Category:Searching]]
 
[[Category:Searching]]

Revision as of 09:45, 28 February 2008

Tip 1543 Printable Monobook Previous Next

[[Vim_Tips_Wiki:New_tips{{{subpage}}}#Find in files within Vim|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.

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.

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

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:

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.

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. 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