How to Use Vim to Replace Text in Multiple Files

How to Use Vim to Replace Text in Multiple Files

Use vim macros and regex replace to speed up your editing

·

4 min read

Problem

You're refactoring a codebase and you need to make the same change across all files:

function greeter() {
  return 'Hello World!';
}

In the example above, we want to rename greeter to greet. Because we're changing the name of the function where it's defined, we need to rename it everywhere it's used as well.

Solution

With vim, you can use a macro to record how to change the function name and then repeat that change across all files.

In this case, the action we're going to repeat is a regular expression search and replace.

TL;DR

Before we go through an in-depth explanation about each step, here's a TL;DR and a video that shows the process in action:

  1. vim **/*.js - tell vim to open all JavaScript files
  2. qa - start recording a macro and store it in the a register
  3. :%s/greeter/greet/g - replace greeter with greet in a single file
  4. :wnext - write the file and move to the next file in the list
  5. q - end the macro recording
  6. @a - replay the macro for the next file
  7. 999@a - replay the macro for the next 999 files (this will end early once the last file is reached)

How To

Great. Now that you know what we're trying to accomplish, let's take a look at how it works in-depth.

1. Open Vim With An Argument List

There are many ways to open vim.

  • vim - opens vim to the startup page
  • vim test.js - opens vim and loads the file test.js
  • vim **/*.js - opens vim with all JavaScript files stored in a list

By using the 3rd option, you can force vim to keep track of all JavaScript files.

Once you're done editing the first file, you can type :wnext to write the file and move to the next file in the list.

2. Start the macro

Macros are a way to record a set of actions, store them, and then replay them on command.

To start a macro:

  1. Press the q key
  2. Press any other key (the macro will be stored to that key's register)

In this case, we'll press qa to start the recording and store the macro in the a register.

3. Regex Replace

In vim you can replace a string in a file by using a regular expression.

We'll type the following to do this: :%s/greeter/greet/g.

Let's break down the above:

  • %s - this tells vim to apply the change within the entire file
  • /greeter/ - this is the text we want to change
  • /greet/ - this is the text we want to change to
  • g - this is a global flag (without this, vim will only replace the text once per line)

4. :wnext

Once we've edited the file, we need to write (save) the file and then go to the next file in the list.

Enter the command :wnext to do this.

5. End the Macro

At this point, we've finished all the steps that we want to save in our macro:

  1. Change the string greeter to greet
  2. Write the file
  3. Move to the next file in the list

To stop the recording, you just need to press the q key again.

6. Replay the Macro

Now that we've recorded the macro, we can replay the steps above to automatically change the text and move to the next file.

You can replay a macro by pressing @a.

There's nothing special about a. It's just the register which is storing the macro. If we had used the register f instead of a above then you'd need to press @f to replay the macro.

7. Replay the Macro x 999

If step 6 succeeded without any errors then it should be safe to replay the macro for the remaining files.

We can take advantage of a vimism which is to enter a number before a command and then type the command. This will tell vim to repeat that action the number of times you entered.

For example, it's common knowledge that to move around a file, you can press j, k, h, l to move the cursor over in one direction.

However, if you press 5j this will tell vim to repeat the move down action 5 times.

We can use a similar trick here and re-run the macro a large number of times.

Press 999@a to re-run the macro stored in the a registry 999 times.

You probably don't have 999 files, but vim will go through every file until it reaches the end. Once it reaches the end, it'll throw an error saying that there are no more files. This error will stop the 999 repeat that we started earlier.

By using the error strategically, we can just repeat the macro a large number of times which will have the effect we want.