Skip to main content

How to Rename Variables Across a File in Vim

·1062 words·5 mins
Linux Learning Lab
Author
Linux Learning Lab
Writing about code, tools, and workflows.

The Problem
#

You have a variable called userData used 30 times in a file and you need to rename it to customerData. You could manually find-and-replace each one, but some occurrences might be inside strings or comments where you don’t want to change them. Vim gives you several approaches depending on how much control you need.

Method 1: Substitution (:%s)
#

The fastest approach when you want to rename every occurrence unconditionally.

Replace all occurrences
#

:%s/userData/customerData/g
PartMeaning
%Entire file
sSubstitute
userDataFind this
customerDataReplace with this
gAll occurrences per line (not just the first)

Replace with confirmation
#

:%s/userData/customerData/gc

The c flag asks you at each match:

KeyAction
yYes, replace this one
nNo, skip it
aReplace all remaining
qQuit substitution
lReplace this one and quit

This is ideal when the variable name might appear in contexts you don’t want to change (comments, strings, similar names).

Whole-word matching
#

Avoid renaming userData inside userDataList or oldUserData:

:%s/\<userData\>/customerData/gc

\< and \> match word boundaries — only the exact word userData matches, not substrings.

Case-sensitive replacement
#

Vim’s substitution respects your ignorecase setting. Force exact case:

:%s/\CuserData/customerData/g

Replace in a specific range
#

" Lines 10 through 50 only
:10,50s/userData/customerData/g

" From current line to end of file
:.,$s/userData/customerData/g

" Inside a visual selection
'<,'>s/userData/customerData/g

Method 2: Star Search + cgn
#

The most flexible approach — you review and decide at each occurrence with minimal keystrokes.

The workflow
#

" 1. Place cursor on the variable name and press * to search for it
*

" 2. Press cgn to change the next match
cgn

" 3. Type the new name
customerData

" 4. Press Esc
Esc

" 5. Press n to find the next occurrence (or N for previous)
n

" 6. Press . to repeat the rename — or n to skip
.

Why this works
#

  • * searches for the exact word under the cursor (whole word match)
  • gn is a motion that selects the next search match
  • cgn = change the next match (deletes it and enters insert mode)
  • . repeats the last change — which was “change next match to customerData”
  • n moves to the next match without changing it (lets you skip)

The power of this approach
#

You get full control at every occurrence:

  • . to rename
  • n to skip
  • No regex to remember
  • Works immediately without typing a substitution command

Method 3: Visual Block Rename
#

When the variable appears in a predictable column position (like a struct or repeated assignments):

struct Config {
    int userData_count;
    char *userData_name;
    float userData_score;
    bool userData_active;
};
" 1. Move cursor to the 'u' in the first 'userData'
" 2. Press Ctrl-v to enter visual block mode
" 3. Select down to cover all occurrences: 3j
" 4. Select the width of 'userData': e (or 7l)
" 5. Press c to change the block
" 6. Type: customerData
" 7. Press Esc — all lines update

This only works when occurrences are aligned vertically.

Method 4: Macro
#

When the rename requires context-aware edits that aren’t easily captured by substitution.

" 1. Search for the variable
/userData

" 2. Start recording a macro into register q
qq

" 3. Change the word
ciwcustomerData

" 4. Press Esc
Esc

" 5. Jump to the next occurrence
n

" 6. Stop recording
q

" 7. Replay with @q, or run many times with a count
20@q

The macro stops when n can’t find another match (end of file).

Selective macro
#

If you want to skip some occurrences:

" Record a macro that changes and advances
qq ciwcustomerData Esc n q

" At each match, decide:
@q    " rename and advance
n     " skip and advance

Method 5: Across Multiple Files
#

When the variable exists in many files, combine approaches:

Using argdo + substitution
#

" Open all files
:args src/**/*.js

" Replace in all of them
:argdo %s/\<userData\>/customerData/gc | update

The | update saves each file after substitution.

Using grep + quickfix
#

" Find all occurrences across the project
:grep "userData" **/*.js
:copen

" Review each match, rename where needed
:cnext
ciwcustomerData Esc
:cnext
.

Using cfdo (quickfix + substitution)
#

" Populate quickfix with matches
:grep "userData" **/*.js

" Run substitution on every file in the quickfix list
:cfdo %s/\<userData\>/customerData/gc | update

Comparing Methods
#

MethodBest when
:%s///gRename all, no exceptions
:%s///gcRename most, skip a few
* + cgn + .Selective, interactive, no regex
Visual blockAligned columns
MacroComplex contextual changes
argdo/cfdoMultiple files

Practical Examples
#

Rename a function and its calls
#

" Whole-word replace across the file
:%s/\<processOrder\>/handleOrder/g

Rename a struct field in C
#

" Be careful — field names may be substrings of other names
:%s/\<node->data\>/node->value/gc

Rename a CSS class
#

" Across HTML and CSS files
:args **/*.html **/*.css
:argdo %s/\<btn-primary\>/btn-main/gc | update

Rename a Python variable with underscore convention change
#

" snake_case to camelCase for one variable
:%s/\<user_data\>/userData/g

Rename in a specific function only
#

" Select the function body with vi{ first
vi{
" Then substitute within selection
:s/\<temp\>/result/g

Note: after visual select, the command line shows :'<,'> automatically.

Tips for Safe Renaming
#

Preview matches first
#

Before any substitution, search for the term and review what will match:

/\<userData\>

Press n to cycle through matches and see if anything unexpected lights up.

Count occurrences
#

:%s/\<userData\>//gn
" Reports: "12 matches on 8 lines" without changing anything

The n flag counts without substituting.

Undo if something goes wrong
#

u           " Undo the entire substitution (one step)
:earlier 1m " Go back 1 minute in time

Vim’s undo treats the entire :%s as one change, so a single u reverts all replacements.

Best Practices
#

  • Always use word boundaries (\< and \>) to avoid renaming substrings
  • Use gc (confirm) when you’re not 100% sure every match should change
  • Use * + cgn + . for interactive renames where you want full control without typing a regex
  • Count first with :%s/old//gn to know how many matches exist before committing
  • For multi-file renames, save with | update in argdo/cfdo so changes persist
  • If a rename goes wrong, u undoes the entire substitution in one step
  • Use :grep + quickfix when you need to review occurrences across files before deciding what to change