Vim Arglist and Grep - Sep 14, 2013

So today, I needed to perform a basic find and replace across many (hundreds) of files. In Vim, it is easy to replace all instances of foo with bar. In fact, it’s as simple as

:%s/foo/bar/g

However, this is only within one file, so to perform this action on multiple files, you need to use the arglist.

If you start vim from the command line with files as an argument, those files are automatically added to the arglist. You can also add to the arglist using the command :argadd from inside vim, but the problem with this method is that adding to the arglist manually can be annoying when you have a lot of files that also cannot be added using standard pattern matching and wildcards (e.g., path/to/files/*.html).

The beauty of the arglist is that once you have all the files you want in it, you can then do

:argdo %s/foo/bar/g | update!

The argdo will perform whichever command that follows on each file in the arglist. The argdo command however does not write and save the file. Therefore we follow up with the update command (followed by a ! to force it to save, just in case you are prevented for some reason).

I knew that I could grep for the term I wanted to replace and end up with a list of the files containing this term by passing the -l flag. So I started looking into how I could get that list into the arglist in vim.

You can’t just simply pipe the output of the grep into the vim command, but luckily Unix also has the xargs command which can turn the grep output into arguments. This means that you can do

grep -l foo | xargs vim

and then vim will open up with all those files in the arglist, then you can run the command above and replace all instances of foo with bar in your entire codebase.