How do I run a substitution over every quickfix hit and save only changed files?
Answer
:cdo s/foo/bar/ge | update
Explanation
When quickfix already contains exactly the lines you want to touch, :cdo is the safest way to batch-edit with tight scope. Instead of running a blind project-wide substitution, you iterate only quickfix entries and write files only when they changed. This makes large refactors both faster and easier to audit.
How it works
:cdoruns the following Ex command on each quickfix entrys/foo/bar/geperforms substitution on each visited linegreplaces all matches on that lineesuppresses “pattern not found” errors so the loop keeps moving| updatewrites only buffers that were modified
This pattern is effective after :vimgrep, :grep, LSP diagnostics exports, or any workflow that materializes a curated quickfix list.
Example
Suppose quickfix is populated with deprecated API hits. Run:
:cdo s/old_api/new_api/ge | update
Vim walks each quickfix target, applies the replacement where it matches, and saves changed files without forcing writes on untouched buffers.
Tips
- Add
cto substitute flags (gec) for per-match confirmations during risky migrations. - Pair with
:copento review entries first and:colder/:cnewerto navigate quickfix history. - Use a more exact regex (word boundaries, namespaces) before running
:cdoto avoid collateral edits.