Home / Learn Linux / Lesson 10
Editing files with Vim
Open, edit, save and quit, then the moves that make Vim fast.
- Lesson
- 10 of 30
- Time
- About 40 minutes
On this page
- Why Vim
- Modes: why Vim feels strange
- Survival: open, type, save, quit
- Moving in Normal mode
- Getting into Insert mode
- Deleting, changing, copying
- Selecting: Visual mode
- Search and replace
- Make Vim nicer: ~/.vimrc
- Root's files: sudoedit
- When Vim says ATTENTION
- Learn the rest: vimtutor
- Common mistakes
- Practice
- Cheat sheet
Why Vim
Sooner or later you'll SSH into a server and need to change a config file. There's no mouse and no desktop, and the one editor you can count on finding on every Linux and Unix machine is vi, or its modern version, Vim. Learn the basics once and you can edit files anywhere.
Ubuntu also has nano, which is simpler and shows its keys at the bottom of the screen (^O means Ctrl+O to save, ^X to exit). Use it if you prefer, but learn enough Vim to survive, because some servers won't have anything else.
Make a practice file first:
$ mkdir ~/vim-lab $ cd ~/vim-lab $ printf "# web server settings\nport = 8080\nhost = localhost\nworkers = 2\ndebug = true\nlog = /var/log/web.log\n" > server.conf $ cat -n server.conf 1 # web server settings 2 port = 8080 3 host = localhost 4 workers = 2 5 debug = true 6 log = /var/log/web.log
Modes: why Vim feels strange
In most editors, every key you press types a letter. In Vim, keys are commands until you say you want to type. That's the one idea that makes Vim click. It has modes:
| Mode | You're in it when | Keys do |
|---|---|---|
| Normal | You open a file, or press Esc | Move, delete, copy, paste |
| Insert | You press i (and others below) | Type text, like any editor |
| Command-line | You press : in Normal mode | Save, quit, search and replace |
| Visual | You press v or V | Select text |
The bottom line of the screen shows -- INSERT -- or -- VISUAL -- when you're in those modes. **When in doubt, press Esc** (twice doesn't hurt). It always takes you back to Normal mode.
Survival: open, type, save, quit
$ vim server.confThen:
- Press
ito start typing. The bottom line shows-- INSERT --. - Type your change. Arrow keys and Backspace work as you'd expect.
- Press
Escto go back to Normal mode. - Type
:wqand Enter to write the file and quit.
| Type (in Normal mode) | Does |
|---|---|
:w | Save |
:q | Quit (refuses if there are unsaved changes) |
:wq or ZZ | Save and quit |
:q! | Quit and throw away your changes |
u | Undo |
Ctrl+R | Redo |
If you're stuck and the file is a mess, Esc then :q! gets you out with nothing changed. That's the most important line in this lesson.
Try it
- Open
server.conf, change8080to9090, save and quit. Check the result withcat.
Answer
vim server.conf, move to the 8080 with the arrow keys, press i, change the number, Esc, :wq and Enter.
$ cat ~/vim-lab/server.conf
# web server settings
port = 9090
host = localhost
workers = 2
debug = true
log = /var/log/web.logMoving in Normal mode
The arrow keys work, but these are faster once your fingers know them:
| Keys | Move to |
|---|---|
h j k l | Left, down, up, right |
w / b | Next word / back a word |
e | End of the word |
0 / ^ / $ | Start of the line / first character / end of the line |
gg / G | First line / last line |
5G or :5 | Line 5 |
Ctrl+D / Ctrl+U | Half a page down / up |
% | The bracket that matches this one |
Turn on line numbers with :set number so you can jump to a line someone mentions, like the line number in an error message. :set nonumber turns them off.
Most commands take a count in front. 3j moves three lines down, 2w two words forward.
Try it
- Open
server.confand jump to the last line, then to line 3, then to the end of that line.
Answer
G, then 3G (or :3 and Enter), then $.
Getting into Insert mode
i is only one of several ways in, and the others save keystrokes:
| Keys | Start typing |
|---|---|
i / a | Before / after the cursor |
I / A | At the start / end of the line |
o / O | On a new line below / above |
A is the one you'll use most for config files: jump to the end of a line and add something. o adds a new setting on the line below.
Try it
- Add a new line
timeout = 30afterworkers = 2.
Answer
Go to the workers line (4G), press o, type timeout = 30, Esc, then :wq.
$ cat ~/vim-lab/server.conf
# web server settings
port = 9090
host = localhost
workers = 2
timeout = 30
debug = true
log = /var/log/web.logDeleting, changing, copying
Editing commands are a verb plus a motion: d (delete) plus w (word) is dw, "delete a word". Doubling the verb works on the whole line.
| Keys | Does |
|---|---|
x | Delete the character under the cursor |
dd | Delete (cut) the line |
dw, d$ (or D) | Delete a word, delete to the end of the line |
cw, cc | Change a word, change the whole line (deletes it and starts Insert mode) |
r then a key | Replace one character |
yy, yw | Copy ("yank") the line, a word |
p / P | Paste after / before the cursor |
. | Repeat the last change |
Counts work here too: 3dd deletes three lines, 5x five characters. And everything you delete goes into a register, so dd then p moves a line: cut it, move, paste.
Try it
- Delete the
debug = trueline. - Copy the
hostline and paste it below itself, then change the copy tohost = 0.0.0.0.
Answer
- Go to it (
/debugand Enter), pressdd. - Go to the
hostline,yythenp. On the new line,cc, typehost = 0.0.0.0,Esc, and:wq.
$ cat ~/vim-lab/server.conf
# web server settings
port = 9090
host = localhost
host = 0.0.0.0
workers = 2
timeout = 30
log = /var/log/web.logSelecting: Visual mode
When a motion isn't enough, select first:
vselects characters as you move.Vselects whole lines.Ctrl+Vselects a rectangle, which is great for columns.
Then press d to delete, y to copy, or > / < to indent or unindent the selection. A classic trick: comment out several lines by selecting them with Ctrl+V down the first column, pressing I, typing # , then Esc.
Try it
- Comment out the
portandhostlines in one go.
Answer
Go to the port line, Ctrl+V, j to also select the host line, I, type # , then Esc. The # appears on both lines after you press Esc.
$ cat ~/vim-lab/server.conf
# web server settings
# port = 9090
# host = localhost
host = 0.0.0.0
workers = 2
timeout = 30
log = /var/log/web.logSearch and replace
| Type | Does |
|---|---|
/word / ?word | Search forward / backward |
n / N | Next / previous match |
* | Search for the word under the cursor |
:s/old/new/ | Replace the first old on this line |
:s/old/new/g | Replace every old on this line |
:%s/old/new/g | Replace every old in the whole file |
:%s/old/new/gc | The same, but ask about each one |
The % means "every line". The patterns are the same regular expressions as grep and sed (lesson 12).
Try it
- Replace every
webwithapiin the file.
Answer
:%s/web/api/g and Enter.
$ cat ~/vim-lab/server.conf
# api server settings
# port = 9090
# host = localhost
host = 0.0.0.0
workers = 2
timeout = 30
log = /var/log/api.logMake Vim nicer: ~/.vimrc
Vim reads ~/.vimrc when it starts. A few lines make it far friendlier:
$ cat > ~/.vimrc << EOF > set number > syntax on > set tabstop=4 shiftwidth=4 expandtab > set ignorecase smartcase > set hlsearch > EOF $ cat ~/.vimrc set number syntax on set tabstop=4 shiftwidth=4 expandtab set ignorecase smartcase set hlsearch
Line numbers, colours, four-space indents, case-insensitive search unless you type a capital letter, and highlighted search results. Any :set command you type inside Vim works in this file without the colon.
Root's files: sudoedit
To edit a file that only root can change, don't run sudo vim. That runs the whole editor as root, along with any plugins and settings. Use sudoedit, which copies the file, opens the copy in your editor as you, and puts it back as root when you quit:
$ sudoedit /etc/hostssudoedit uses the editor named in the EDITOR variable, and Ubuntu's default is nano. To make it Vim, add this to ~/.bashrc:
$ echo 'export EDITOR=vim' >> ~/.bashrc $ source ~/.bashrc
If you forgot and opened a root file in Vim as yourself, you'll get a warning that it's read-only. :w !sudo tee % > /dev/null saves it anyway: it sends the buffer to sudo tee and writes it to the current file (%), the same sudo tee trick from lesson 8.
When Vim says ATTENTION
While a file is open, Vim keeps a hidden swap file next to it, like .server.conf.swp, so nothing is lost if your SSH connection drops. If you open a file that has a swap file, Vim stops with E325: ATTENTION and asks what to do:
- If another Vim is still editing the file (another terminal), quit with
Qand go finish there. - If your connection dropped, press
Rto recover the unsaved changes, save with:w, then delete the old swap file:rm .server.conf.swp.
Learn the rest: vimtutor
Vim comes with a 30-minute interactive lesson. Run vimtutor, and it opens a practice copy of the tutorial that you edit as you read. It's the fastest way to make all of this stick, and you can do it again any time.
Common mistakes
- Typing while in Normal mode. Letters run commands, and the file gets mangled. Press
Esc, thenuuntil it's back, thenibefore you type. - Not knowing how to leave.
Esc, then:q!. - Caps Lock on. In Normal mode,
J,Kand the rest of the capitals do different things from their lowercase versions. If Vim goes wild, check Caps Lock. - **
sudo vimfor every system file.** Usesudoedit. - Deleting the swap file while Vim still has the file open somewhere. Check for another session first.
Practice
Start from a fresh copy of the practice file, then do these in order, each one on the result of the last:
$ printf "# web server settings\nport = 8080\nhost = localhost\nworkers = 2\ndebug = true\nlog = /var/log/web.log\n" > server.conf- Change
workers = 2toworkers = 8usingcwon the number.
Answer
/workers Enter, $ to the end of the line (the cursor lands on 2), cw, type 8, Esc, :wq. (r8 would also work, since it's one character.)
$ grep workers ~/vim-lab/server.conf
workers = 8- Move the
logline so it's the second line of the file.
Answer
G to the last line (the log line), dd to cut it, gg to the first line, p to paste below it, then :wq.
$ cat ~/vim-lab/server.conf
# web server settings
log = /var/log/web.log
port = 8080
host = localhost
workers = 8
debug = true- Add
;to the end of every line except the comment, with one command.
Answer
:2,$s/$/;/ and Enter. 2,$ means line 2 to the last line, and $ in the pattern means the end of each line.
$ cat ~/vim-lab/server.conf
# web server settings
log = /var/log/web.log;
port = 8080;
host = localhost;
workers = 8;
debug = true;- Delete lines 3 to 5 with one command in Normal mode.
Answer
3G then 3dd. Or from the command line: :3,5d.
$ cat ~/vim-lab/server.conf
# web server settings
log = /var/log/web.log;
debug = true;- Make a mess on purpose (press random keys in Normal mode), then get the file back exactly as it was without saving.
Answer
Esc then :q!. Or undo everything with u repeatedly, or :e!, which reloads the file from disk.
- Make
EDITOR=vimpermanent, then open/etc/hostswithsudoeditand quit without changes.
Answer
$ echo 'export EDITOR=vim' >> ~/.bashrc $ source ~/.bashrc $ sudoedit /etc/hosts
Vim opens the file. :q to leave.
Cheat sheet
| Keys | What they do |
|---|---|
i, a, I, A, o, O | Start typing: before, after, line start, line end, new line below, above |
Esc | Back to Normal mode |
:w, :q, :wq, ZZ, :q! | Save, quit, both, both, quit without saving |
h j k l, w b e | Move by character, by word |
0 ^ $, gg G, 5G | Line start/first char/end, file start/end, line 5 |
x, dd, dw, D | Delete char, line, word, to line end |
cw, cc, r | Change word, line, one character |
yy, p, P | Copy line, paste after, before |
u, Ctrl+R, . | Undo, redo, repeat |
v, V, Ctrl+V | Select characters, lines, a block |
/word, n, N, * | Search, next, previous, word under cursor |
:%s/old/new/g | Replace everywhere (gc to confirm each) |
:set number | Line numbers |
~/.vimrc | Your settings |
sudoedit file | Edit a root-owned file safely |
vimtutor | The built-in 30-minute lesson |
← Finding files and text: find, locate and grepArchives and links: tar, gzip, hard links and symlinks →