vimtricks.wiki Concise Vim tricks, one at a time.

How do I search and replace text across multiple files in Vim?

Answer

:args **/*.py | argdo %s/old/new/gc | update

Explanation

Vim can perform search-and-replace across multiple files without any plugins by combining the arglist with :argdo. You load files into the argument list, then run a substitution on every file in one command chain.

How it works

  • :args **/*.py populates the argument list with all .py files recursively in the current directory
  • | chains Ex commands together
  • :argdo %s/old/new/gc runs the substitution on every file in the arglist
  • The c flag gives you interactive confirmation at each match (omit it to replace all silently)
  • | update saves each file only if it was modified (safer than :w which writes unconditionally)

Example

Rename a function across your entire Python project:

:args **/*.py | argdo %s/\<calculate_total\>/compute_total/g | update

This finds every .py file, replaces all whole-word occurrences of calculate_total with compute_total, and saves each changed file.

For a narrower scope, use :vimgrep and the quickfix list instead:

:vimgrep /calculate_total/ **/*.py
:cfdo %s/calculate_total/compute_total/gc | update

:cfdo only operates on files that actually contain matches, which is faster when you have many files but few matches.

Tips

  • Use :args without arguments to see the current argument list
  • Add e to the substitute flags (/gce) to suppress errors on files with no matches, preventing the command from aborting early
  • Use \< and \> word boundaries to avoid partial matches: :%s/\<old\>/new/g
  • :argdo and :cfdo both support any Ex command, not just :s — you can run :norm, :g, or :delete across files too
  • Always version-control your project before running bulk replacements so you can review the diff and revert if needed
  • Use :bufdo %s/old/new/ge | update if the files are already open as buffers
  • The quickfix approach (:vimgrep + :cfdo) is generally preferred because it only touches files with actual matches

Next

How do I edit multiple lines at once using multiple cursors in Vim?