Batch Editing Files with Vim

style-newspaper len:7022 crease:22% color:2

Vim: great for trapping your coworkers, but also a ridiculously powerful batch-editing beast. Let’s process some files from the terminal without even looking at a UI.

Here’s our victim, post.md:

---
title: Awesome tips
tags:
  - tech
---
An awesome post.

1. Quick & Dirty Command Line Edits

Need to change “tips” at the end of a line to “Tips”? Skip the interface and just yell at Ex mode (-e) silently (-s):

vim -es -c '%s/tips$/Tips/' -c x post.md
  • -c: Runs an Ex command.
  • x: Save (only if changed) and quit, quote it if you really want. wq is for people who love unnecessary disk writes.

2. When Things Get Complicated: Vim Scripts

Let’s say you want to:

  1. Fix that “tips$” typo.
  2. Inject a new tip tag.
  3. Sort the tags list.

Jam it all into an edit.vim file:

" 1. Fix typo
%s/tips$/Tips/

" 2. Append a tag like a civilized person (dot means "end of text")
/tags:/a
  - tip
.

" 3. Sort and uniq (:help sort)
/tags:/+1,/^---/-1 sort u

" Save and exit
x

Run it with -S (source):

vim -es -S edit.vim post.md

Or violently redirect it into standard input:

vim -es post.md < edit.vim

3. Scriptless Chaos (The Inline Way)

Too lazy to make a script file? Chain your -c commands.

To insert the tag here, we ditch a (append). Why? Because a expects a multi-line newline-terminated block, which is a nightmare to escape in a bash string.

Enter the put trick. put =' - tip' evaluates a literal string expression (the =) and drops it right below your cursor. Boom. One line.

vim -es -c '%s/tips$/Tips/' -c "/tags:/put ='  - tip'" -c '/tags:/+1,/^---/-1 sort u' -c x post.md

(Warning: Quoting might cause mild brain damage.)

4. xargs Will Break Your Heart

You want to edit a hundred files. Your brain says, “Hey, xargs!”

find . -name '*.md' | xargs vim -es -S edit.vim

Vim hangs, and you curse after several attempts. Why? Because vim processed the first file, closed it, then opened the second and was waiting for more inputs!

“But wait!” you say, “I’ll use -n1!”

find . -name "*.md" | xargs -n1 vim -es -S edit.vim

Congrats, it works. But now you’re spawning a brand new Vim process for every single file. If you have a massive codebase, this is glacially slow.

The Real Solution: argdo

Pass all files to a single Vim instance and let Vim iterate through them like the champ it is.

vim -es -c 'argdo source edit.vim | update' -c qa *.md
  • argdo: Do this to everything in the argument list.
  • update: Save only if changed (again, disk writes!).
  • qa: Quit all.

Batch Editing Files with Vim

style-newspaper len:7022 crease:22% color:2
Jun 28, 2026

Vim: great for trapping your coworkers, but also a ridiculously powerful batch-editing beast. Let’s process some files from the terminal without even looking at a UI.

Here’s our victim, post.md:

---
title: Awesome tips
tags:
  - tech
---
An awesome post.

1. Quick & Dirty Command Line Edits

Need to change “tips” at the end of a line to “Tips”? Skip the interface and just yell at Ex mode (-e) silently (-s):

vim -es -c '%s/tips$/Tips/' -c x post.md
  • -c: Runs an Ex command.
  • x: Save (only if changed) and quit, quote it if you really want. wq is for people who love unnecessary disk writes.

2. When Things Get Complicated: Vim Scripts

Let’s say you want to:

  1. Fix that “tips$” typo.
  2. Inject a new tip tag.
  3. Sort the tags list.

Jam it all into an edit.vim file:

" 1. Fix typo
%s/tips$/Tips/

" 2. Append a tag like a civilized person (dot means "end of text")
/tags:/a
  - tip
.

" 3. Sort and uniq (:help sort)
/tags:/+1,/^---/-1 sort u

" Save and exit
x

Run it with -S (source):

vim -es -S edit.vim post.md

Or violently redirect it into standard input:

vim -es post.md < edit.vim

3. Scriptless Chaos (The Inline Way)

Too lazy to make a script file? Chain your -c commands.

To insert the tag here, we ditch a (append). Why? Because a expects a multi-line newline-terminated block, which is a nightmare to escape in a bash string.

Enter the put trick. put =' - tip' evaluates a literal string expression (the =) and drops it right below your cursor. Boom. One line.

vim -es -c '%s/tips$/Tips/' -c "/tags:/put ='  - tip'" -c '/tags:/+1,/^---/-1 sort u' -c x post.md

(Warning: Quoting might cause mild brain damage.)

4. xargs Will Break Your Heart

You want to edit a hundred files. Your brain says, “Hey, xargs!”

find . -name '*.md' | xargs vim -es -S edit.vim

Vim hangs, and you curse after several attempts. Why? Because vim processed the first file, closed it, then opened the second and was waiting for more inputs!

“But wait!” you say, “I’ll use -n1!”

find . -name "*.md" | xargs -n1 vim -es -S edit.vim

Congrats, it works. But now you’re spawning a brand new Vim process for every single file. If you have a massive codebase, this is glacially slow.

The Real Solution: argdo

Pass all files to a single Vim instance and let Vim iterate through them like the champ it is.

vim -es -c 'argdo source edit.vim | update' -c qa *.md
  • argdo: Do this to everything in the argument list.
  • update: Save only if changed (again, disk writes!).
  • qa: Quit all.

Just a Normal Grocery Run in Switzerland

style-polaroid len:142 crease:43% color:1

从超市购物小票一瞥🇨🇭生活成本

Just a Normal Grocery Run in Switzerland

style-polaroid len:142 crease:43% color:1
Jan 8, 2026

从超市购物小票一瞥🇨🇭生活成本