Can a developer live without a good search engine in his editor or IDE? What developer never used the famous find and replace in multiple files?
You can be happy though, dear Vim user: your editor totally shine by its search features! With a minimum of configuration you can be able to search whatever you want, wherever you want at light speed.
You need to use Vim to find and replace occurrences in thousand of files and filter with a maximum of granularity? This article will teach you the “how” if you are ready to learn it.
A little precision: I will often refer to Vim current working directory in this article. To know what directory it is for you, execute in Vim the ex command
:pwd. To change it, you can use
Enough small talk. Let’s dive in!
Search and replace in vanilla Vim
Learning vanilla Vim capabilities without trying plugins at first allow you to be efficient regardless of Vim’s configuration.
Being efficient in Vim without your precious vimrc is priceless. Specially when you are lost on a remote server trying to fix-quickly-this-wrong-configuration-which-crash-the-whole-thing.
Vim search in the current file
In order to search in the current open file, you just need to type
/ in normal mode.
Then you need to type your search pattern and the result become highlighted in your file.
To go back and forth through the results, you can type
n to go forward in the file and
N to go backward.
/ will search forward in the file. If you need to directly search backward, you can use
Setting the search highlights
It is very practical to see the search highlighted in the file. However in Vim it’s not activated by default. To activate it, you can type
:set hlsearch or set it in your
If you use Neovim, the highlighting is set by default.
Clearing the last search highlight
:noh in normal mode will clear this highlight you tried to get rid off by trying (almost) every button on your keyboard.
Since you don’t really want to type this command each time you do a search (we are all lazy here), you can map a key to the command in your vimrc as follow:
map <esc> :noh<cr>.
Each time you will type
esc, you will clear the last search highlighted and therefore keep your sanity. Lucky you.
Searching the word under the cursor
- Place your cursor on the word you want to search
/, every results will be highlighted.
To search for partial words (include word parts in the results), you can use the keystroke
Vim search case insensitive
/search\c- Search with case insensitive
/search\C- Search with case sensitive
You can as well write the following command in your vimrc:
set ignorecase- All your searches will be case insensitive
set smartcase- Your search will be case sensitive if it contains an uppercase letter
Be aware that
ignorecase needs to be set for
smartcase to be set as well.
Vim search in multiple files
The quickfix window after executing
vimgrep kernel **/*.php and
vimgrep will populate the quickfix list (see
:help quickfix and
:help quickfix-window in Vim) with the result of the search.
It implies that you need to use the command
:cprev to go through the results (instead of
You can as well open the quickfix window with
:copen and go through the results.
:vimgrep pattern *will search in every files of the working directory the word “pattern”.
:vimgrep pattern a.txt b.txt c.txtwill search the same word only in the files a.txt, b.txt and c.txt.
:vimgrep pattern *.phpwill search “pattern” in every php files
:vimgrep pattern **/*.phpwill search “pattern” in every php files in the working directory and every subdirectories
Quick tip: since the command
@: repeat your last command, you can go through all your results by taping
:cnext and then only using the
For more information about
vimgrep, I strongly advice you to look at the excellent vimcast about it.
Last but not least: you should read Vim’s help about vimgrep by typing
Vim search using the command grep
Vimgrep is good but unfortunately pretty slow. As an alternative you can use the external program grep directly in Vim. Obviously you need
grep to be installed on your machine.
Using grep and
vimgrep is similar. For example:
:grep mySearch *will search every occurences of
mySearchin the working directory
:grep mySearch a.txt b.txt c.txtwill search every occurences of
mySearchin the files a.txt, b.txt, c.txt
I won’t cover here every use of
grep. You can read more about it in the official grep manual. For its use in Vim you can type in Vim
Vim find and replace
Vim substitute in the current file
Vim has a very powerful find and replace functionality thanks to the
Let’s look at some examples:
:s/pattern/replace/gchange each “pattern” by “replace” on the current line
:%s/pattern/replace/gchange each “pattern” by “replace” in the current file
:%s//replace/gchange your last search by “replace” in the current file
You may ask: what the hell those letters and signs mean? You’re curious, I like that.
- The letter
- The keyword
%will target the entire file instead of the current line.
- The keyword
gmeans “global” - more than one occurrences are targeted
Those are the most common
substitute command you will use. Nevertheless I encourage you to consult Vim’s help (again?) by typing
Note that the
substitute command can be grandly enhanced by the excellent Tim Pope’s vim-abolish plugin. A must have for every cool Vim users out there!
And I know you’re cool.
This substitute will crash Symfony 4 kernel
Vim find and replace one occurrence at a time
It’s very simple to search and then decide if you want to keep or replace each result in a file:
- Execute a regular search like
- Use the keystroke
cgnon the first result to replace it
Nto go to the next result
.to replace the occurrence with the same replacement (or go to the next result if you want to keep it)
What is this
cgn keystroke you may ask? What does it mean?
If you read
:help gn you will see that
gn is the same as
n but will as well start Visual mode and select the occurrence. We just do a change (
c) on the next (selected) search occurrence.
From there you can can easily understand that things like
dgn will work as well.
With this simple technique you can do a granular find and replace in the whole file.
Vim find and replace in files
You can use the excellent Vim arglist to do so. Think of it as an internal list of files you can populate and modify.
If you want to replace an occurrence in every
twig files, you can type the following:
:arg *.html- Empty the buffer and populate the arglist with all
htmlfile in the current working directory
:argadd *.twig- Add
twigfiles to the arglist
:argdo %s/pattern/replace/ge | update- Replace the occurence
replacein every files of the arglist
At that point you may scream to your screen, shacked violently by curiosity: what means
e at the end of the
It simply prevent Vim to display an error message when the pattern is not found in a file.
What about doing a find and replace for the files in the working directory and subdirectories? You need to populate the arglist as follow:
You need to find and replace in the open buffer? Well, it’s easy. I expected you to have more difficult questions. Simply execute:
:bufdo %s/pattern/replace/ge | update
Do you know what I encourage you to read? Yes:
Vim search with external plugins
I have a good new: there are better alternatives for
grep or using the
arglist to find and replace in files. The plugins described here will change your search life!
Be aware: I won’t cover every search plugins available. There are simply too many and I ’m too lazy for that. However I will give you the most powerful combo for any of your search needs.
That’s all we want, isn’t it?
Since we speak about Vim plugins, I wrote another article which list the necessary Vim plugins to build a Vim PHP IDE. In case you’re interested.
One Plugin to rule them all, One Plugin to find them
If there was one plugin I would take with me on a lost inhabited island (with a computer and Vim) it would be fzf.vim coupled with the command line fuzzy finder fzf. This is a must have. I beg you to try it and here’s why:
- It’s blazing fast (written in Go). Einstein was wrong: you can go beyond light speed
- It allows you to search in your terminal whatever file or history entry you want
- It can be coupled with Vim to search a lot of useful things like buffers, open files history…
Here some basic examples:
:Files- Search a file in your working directory and subdirectories
:Buffers- Search a file open in one of your buffer
:History- Search a file in your open file history
Simple and highly configurable!
Vim search in multiple files with Ripgrep
fzf is a powerful tool but it’s not enough to search a precise occurrence in a whole bunch of files. You need another crazy fast terminal program: ripgrep.
Ripgrep coupled with fzf will bring under your little fingers the best search engine I’ve ever seen in any IDE. No more, no less.
In order to link fzf with ripgrep, you can look to my fzf config file on github.
Then you just have to enter the command
:Rg pattern to search “pattern” in every files of the working directory. Mind blowing.
The sweet combo fzf / ripgrep
You can use as well
ripgrep instead of
grep for the
Vim find and replace in multiple files with Vim ferret
The last plugin I use is ferret. It allows you to search an occurrence in multiple files, select what results you want to replace and finally replace them.
Moreover if you have ripgrep installed on your system, this plugin will use it by default!
:Ack patternwill search in the working directory
:Ack pattern /path/to/directorywill search in the specified path and its subdirectories
At that point Ferret will populate the quickfix window with every results found.
You can delete the result by typing
dd in case you don’t want to replace it. You can as well type enter to open the file with the result highlighted.
:Acks /pattern/replacement/ will replace every results still present in the quickfix window.
Simple, granular, powerful: that’s what we want!
Vim is now a search-killing-machine
This overview will bring you whatever search functionality you need as a developer.
I personally use built-in vim search functionality when I search (or search in replace) in one file. When the search operation needs to be in a whole project or on multiple files, I use fzf, ripgrep and ferret.
If you know other functionalities / plugins which can bring even more coolness in our life, please don’t hesitate to let a comment!
You know, sharing is caring.