Two weeks ago on Into the Terminal, we went deep on vim — from the essential commands every sysadmin needs, to multipliers, macros, visual blocks, and customizing your .vimrc. Whether you're brand new to vim or you've been using it for years and just never learned beyond :wq, this one's for you.
Watch the full episode: https://youtube.com/live/UfzjXbLVwwo
Try it yourself on a live lab: https://redhat.com/interactive-labs
The Essential ~15 Commands
You can be minimally proficient in vim with about 13–15 commands. Everyone's list is a little different — here's what our two hosts use, and where they differ.
Getting In and Out of Insert Mode
| Command |
What it does |
i |
Enter insert mode at the cursor |
I |
Enter insert mode at the beginning of the line (great for adding # to comment a line out) |
a |
Enter insert mode after the cursor (append) |
Esc |
Exit insert mode and return to normal/command mode |
Moving Around
| Command |
What it does |
| Arrow keys |
Move around (works in vim improved) |
h j k l |
Classic movement — left, down, up, right (required on older vi implementations where arrow keys don't work) |
w / b |
Jump forward/backward by word boundary |
W / B |
Jump forward/backward by whitespace-delimited word (bigger jumps) |
G |
Go to the end of the file |
20G |
Go to line 20 |
:20 |
Also go to line 20 (command-line style) |
:$ |
Go to the last line of the file |
$ |
Move to end of the current line |
^ |
Move to beginning of the current line |
Pro tip from the show: You can also open a file at a specific line number from the shell:
vim +20 myfile.conf
Handy when your compiler tells you there's a syntax error on line 20.
Deleting / Cutting
| Command |
What it does |
dd |
Delete (cut) the entire current line |
D |
Delete from cursor to end of line |
d + arrow |
Delete one character in the arrow direction |
d$ |
Delete from cursor to end of line (same as D) |
d^ |
Delete from cursor to beginning of line |
x |
Delete the character under the cursor |
Copy (Yank) and Paste
| Command |
What it does |
yy |
Yank (copy) the current line |
p |
Paste below the current line |
dd then p |
Cut a line and paste it somewhere else — this is how you move lines |
Note: dd puts the deleted line into a buffer, so it doubles as "cut." This terminology predates the modern "copy/paste" — back when vi was created, the terms were yank (copy) and delete (cut).
Undo
| Command |
What it does |
u |
Undo the last change. Keep pressing to walk back through your history. |
In vim improved, u walks back through your full edit history. In classic vi, it only undoes the last command. Also note: undo history is per-session — if you quit and reopen the file, the history is gone.
Save and Quit
| Command |
What it does |
:w |
Write (save) the file |
:q |
Quit |
:wq |
Write and quit |
:q! |
Quit without saving (force quit) |
:w! |
Force write (only works with elevated permissions like root — lets you override file permissions) |
Note: :w! won't help on a read-only filesystem. That's enforced at the filesystem level, not the permission level.
Advanced Features
Multipliers — Do Anything N Times
Prefix any command with a number to repeat it.
| Example |
What it does |
5dd |
Delete 5 lines (and put them all in the cut buffer) |
500p |
Paste 500 copies of whatever is in your buffer |
30j |
Move down 30 lines |
100@t |
Execute macro t 100 times |
5000dd |
Delete 5000 lines, handy for deleting the rest of a file. (if <5000 lines remain, it just stops at the bottom) |
Line Anchors — ^ and $ in Combination
The ^ (beginning) and $ (end) characters aren't just for movement. You can combine them with other commands:
| Example |
What it does |
d$ |
Delete from cursor to end of line |
d^ |
Delete from cursor to beginning of line |
:1,$s/old/new/g |
Search and replace from line 1 to the end of the file |
:$ |
Jump to the last line of the file |
By learning just ^ and $ as anchors, you get multiple delete behaviors without memorizing separate commands for each.
Search
| Command |
What it does |
/searchterm |
Search forward for "searchterm" |
/ + Enter |
Repeat last search forward |
?searchterm |
Search backward for "searchterm" |
Search and Replace (Substitution)
| Command |
What it does |
:s/old/new/ |
Replace first occurrence of "old" with "new" on the current line |
:s/old/new/g |
Replace all occurrences on the current line |
:%s/old/new/g |
Replace all occurrences in the entire file |
:1,$s/old/new/g |
Same as above, using line anchors (line 1 to end) |
:10,20s/old/new/g |
Replace only between lines 10 and 20 — great for targeting a single function or block |
Reading Files and Command Output Into Your Buffer
| Command |
What it does |
:r filename |
Read the contents of filename and insert it below the cursor |
:r /var/log/messages |
Works with full paths too |
:r !df -hp |
Run df -hp and insert its output directly into your file |
:!command |
Run an external command and see the output (press Enter to return to vim) |
The :r !command trick is a time-saver — no need to run a command, redirect to a file, then :r that file.
Security note: :! lets you run any shell command. If someone has sudo access to run vim as root, they can shell out from vim with full root privileges. Use the NOEXEC option in sudoers to prevent forking from within escalated sessions.
Saving to a Different File
| Command |
What it does |
:w /path/to/newfile |
Save the current buffer to a new file (the original stays untouched) |
Great for making a backup before committing changes, or for cleaning up data and writing the result to a new file while preserving the original.
Visual Block Mode — Comment Out Code in Bulk
- Press
Ctrl+V to enter visual block mode
- Use arrow keys (or
j/k) to select the lines you want
- Press
I (capital I) to insert at the beginning of the block
- Type your comment character (e.g.,
#)
- Press
Esc — the character appears on all selected lines
This is how you comment out a block of code in seconds. Works great for Python, shell scripts, config files — anything with a line-based comment character.
Pasting Pre-formatted Code Without Mangling
Vim's auto-indent is great when you're writing code, but it wrecks pre-formatted code that you paste in from your clipboard.
| Command |
What it does |
:set paste |
Enter paste mode — disables auto-indent so pasted code keeps its formatting |
:set nopaste |
Return to normal mode with auto-indent re-enabled |
When paste mode is on, you'll see -- INSERT (paste) -- at the bottom. This is much easier than the alternative of typing :set noautoindent nosmartindent nocindent.
Macros (Named Buffers) — Record and Replay Commands
q + a letter (e.g., qt) — start recording to buffer t
- Perform your commands (move, delete, edit, etc.)
q — stop recording
@t — execute the macro stored in t
@@ — re-execute the last macro
100@t — execute macro t 100 times (multipliers work here too)
Use :reg to view all your named buffers and see exactly what commands are stored in each one.
Example from the show: We had a CSV file with 114 lines that needed the same edit on every line. Instead of doing it by hand, we recorded a macro that moved down a line, repositioned the cursor, deleted the unwanted data, and then replayed it across the entire file with 100@t. Seconds instead of minutes.
Customizing Your Session (and Your .vimrc)
All of these can be run as one-off commands with :set, or persisted by adding them to your ~/.vimrc file.
| Setting |
What it does |
:set tabstop=N |
Set tab width to N spaces (default is 4) |
:set expandtab |
Insert spaces instead of a literal tab character |
:set hlsearch (or hls) |
Highlight all search matches |
:set nohlsearch |
Turn off search highlighting |
:noh |
Clear the current highlight without turning the feature off |
:syntax on / :syntax off |
Toggle syntax highlighting (note: no set prefix — syntax is its own command) |
:set cursorcolumn (or cuc) |
Highlight the column you're in — a lifesaver for YAML and Python |
:set number / :set nonumber |
Show/hide line numbers |
:set showmode / :set noshowmode |
Show/hide the mode indicator (INSERT, VISUAL, etc.) at the bottom |
:set showcmd / :set noshowcmd |
Show/hide partially-typed commands at the bottom |
:set paste / :set nopaste |
Toggle paste mode (see above) |
:set |
View all currently active settings |
RHCE exam tip from the show: When you sit down to take the exam, put :set cuc and :set number in your .vimrc first. The cursor column highlighting will save you when editing Ansible playbooks and YAML files.
The Pattern for Set Commands
- Turn something on:
:set feature
- Turn something off:
:set nofeature
- Some settings use
= syntax: :set tabstop=4
- Some commands like
syntax don't use set at all: :syntax on
Quick Reference Card
GETTING AROUND EDITING SAVE/QUIT
i insert mode dd delete line :w save
I insert at line start D delete to end of line :q quit
a append after cursor d^ delete to line start :wq save & quit
Esc back to normal yy copy line :q! quit no save
/ search forward p paste :w! force save
? search backward u undo
G end of file x delete character
:20 go to line 20
POWER MOVES SETTINGS (in :set or .vimrc)
5dd delete 5 lines tabstop=N tab width
Ctrl+V visual block expandtab spaces not tabs
qt...q record macro t hlsearch highlight matches
u/t play macro t cursorcolumn column highlight
100@t play macro 100x number line numbers
:%s/a/b/g replace all paste paste mode
:r !cmd read cmd output syntax on syntax highlighting
Links
Into the Terminal is a weekly livestream covering critical administration skills for Red Hat Enterprise Linux. Whether you're new to Linux or new to RHEL, join us for hands-on looks at commands and processes, ask questions, and grow your knowledge.