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

How do I run a search and replace across multiple files?

Answer

:cfdo %s/old/new/g | update

Explanation

The :cfdo %s/old/new/g | update command performs a search and replace across every file in the quickfix list and saves each one. This is the standard Vim workflow for project-wide find-and-replace without any plugins.

How it works

  • :cfdo executes a command once for each file in the quickfix list
  • %s/old/new/g runs the substitution on every line of the current file
  • | update saves the file only if it was modified (like :w but smarter)

Step-by-step workflow

  1. Populate the quickfix list with matching files using :vimgrep or :grep:
:vimgrep /oldFunction/g **/*.js
  1. Review the matches with :copen to see the quickfix window.

  2. Run the replacement across all files:

:cfdo %s/oldFunction/newFunction/g | update

Every JavaScript file containing oldFunction now has it replaced with newFunction, and each modified file is saved automatically.

cfdo vs cdo

  • :cfdo runs the command once per file in the quickfix list — use this for substitutions
  • :cdo runs the command once per entry (match) in the quickfix list — use this for targeted, per-match operations

Handling special characters

When your search or replacement string contains special characters like /, use \V (very nomagic) mode for literal matching and escape forward slashes:

:cfdo %s/\V\Ctext\/html/application\/json/g | update
  • \V treats all characters literally (except \)
  • \C forces case-sensitive matching
  • \/ escapes the forward slash within the pattern

Tips

  • Always review the quickfix list with :copen before running :cfdo to make sure you are targeting the right files
  • Use :cfdo %s/old/new/gc | update with the c flag to confirm each replacement interactively
  • Use :vimgrep to populate the quickfix list from within Vim, or :grep to use an external tool like rg or ag
  • Omit | update if you want to review changes before saving — then use :cfdo update separately to save all modified buffers
  • This requires Vim 8+ or Neovim — older versions do not have :cfdo
  • Use :bufdo %s/old/new/g | update as an alternative if you already have the target files open as buffers

Next

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