How to Use Vim and vi: Edit, Save and Exit
Vim is installed on almost every Linux server, and vi is usually a minimal build of Vim. It is also what git commit, crontab -e or visudo may open when no other editor is configured. A handful of commands is enough to edit config files comfortably, and to avoid the classic situation where a file is open, typing does strange things and nothing seems to close it.
How to exit Vim
Press Esc (twice does no harm) to get back to Normal mode. Then type one of these:
| Command | What it does |
|---|---|
:q | quit, works only when there are no unsaved changes |
:q! | quit and throw away changes |
:wq | save and quit |
:x or ZZ | save only if something changed, then quit |
ZQ | quit without saving |
:wqa | save all open files and quit |
:qa! | quit everything, discard all changes |
Commands that start with : appear at the bottom of the screen and need Enter. ZZ and ZQ (capital letters) act immediately.
The error messages you are likely to see:
E37: No write since last change (add ! to override): there are unsaved changes. Use:wqto keep them or:q!to drop them.E45: 'readonly' option is set (add ! to override): the file was opened read-only, for example withview. If you own it,:w!saves anyway.E212: Can't open file for writing: you have no permission, typically a file in/etcopened withoutsudo. Save a copy with:w /tmp/hosts.newand quit, or in Vim (not Neovim) write through sudo with:w !sudo tee % > /dev/null. Next time, open the file withsudoedit /etc/hosts.
If the screen stops reacting, you may have pressed Ctrl+S, which pauses terminal output. Ctrl+Q resumes it. Ctrl+Z suspends Vim and drops you to the shell; fg brings it back.
Modes
Vim is modal. The same key does different things depending on the mode:
- Normal: the default. Keys are commands, so
dddeletes a line anduundoes. - Insert: keys insert text. The bottom line shows
-- INSERT --. - Visual: select text with
v(characters),V(lines) orCtrl+v(a block). - Command-line: after typing
:,/or?.
Esc always takes you back to Normal mode.
Open a file
vim notes.txt # opens it, or creates it on first save
vim +42 app.py # cursor on line 42
vim +/listen nginx.conf # cursor on the first match
view /etc/fstab # read-only
vimdiff a.conf b.conf # side-by-side diff
Write text
From Normal mode, enter Insert mode with:
iinsert before the cursor,aafter itIinsert at the start of the line,Aat the endoopen a new line below,Oabove
Type the text, press Esc, then save with :w. To save under another name, :w new.txt writes a copy and keeps you in the current file, while :saveas new.txt switches to the new file.
Modern Vim handles pasting into the terminal automatically. If pasted code still turns into a staircase of growing indentation, run :set paste before pasting and :set nopaste after.
Move around (Normal mode)
hjkl: left, down, up, right (arrow keys work too)wandb: next and previous word,eto the end of a word0,^,$: start of line, first non-blank character, end of lineggandG: first and last line,42Gor:42for line 42Ctrl+dandCtrl+u: half a page down and up%: jump to the matching bracket
Edit (Normal mode)
x: delete the character under the cursordd: delete (cut) the line,5ddfor five linesdw: delete a word,Dto the end of the linecw: change a word (delete it and enter Insert mode)r: replace one characteryy: copy (yank) the line,ywa wordpandP: paste after and before the cursoruundo,Ctrl+rredo.: repeat the last change>>and<<: indent and unindent the line
Operators like d, c and y combine with any motion, and a number repeats it: d$ deletes to the end of the line, y3w copies three words, ci" changes the text inside quotes, 3dd deletes three lines. This is where Vim gets fast.
Visual mode
Press v, V or Ctrl+v, move to extend the selection, then act on it: d to delete, y to copy, > to indent, or : to run a command on the selected lines. To comment out several lines: Ctrl+v, move down with j, press I, type # , then Esc, and the text appears on every line.
Search and replace
/listen search forward, n for next, N for previous
?error search backward
* search for the word under the cursor
:%s/old/new/g replace everywhere in the file
:%s/old/new/gc replace everywhere, confirm each one
:10,20s/^/# / add "# " at the start of lines 10 to 20
:noh clear search highlighting
Add \c to a pattern to ignore case for one search, for example /error\c.
The swap file warning
E325: ATTENTION ... Found a swap file by the name ".config.yml.swp" means the file is either open in another Vim session or a previous session crashed. The prompt offers:
Oopen read-only,Eedit anywayRrecover unsaved changes from the swap fileDdelete the swap file (only offered when the session that created it is gone)Qquit,Aabort
If another session has the file open, quit and finish there; two editors on one file will overwrite each other. After a crash, choose R, check the content, save, and delete the .swp file.
A minimal ~/.vimrc
set number
syntax on
set expandtab tabstop=4 shiftwidth=4
set ignorecase smartcase
set hlsearch incsearch
vi, Vim and the default editor
vi on Debian and Ubuntu is often vim-tiny, and on the RHEL family it is vim-minimal. The commands above work in both, but syntax highlighting and other features need the full package: sudo apt install vim or sudo dnf install vim-enhanced. The full package also includes vimtutor, an interactive lesson of about half an hour that is the fastest way to build the muscle memory.
To choose which editor other tools open, set EDITOR and VISUAL in ~/.bashrc, or pick per tool:
export EDITOR=vim VISUAL=vim
git config --global core.editor vim
sudo update-alternatives --config editor # system default on Debian, Ubuntu
Set them to nano instead if you would rather not use Vim at all.
Quick reference
Esc back to Normal mode
:w save
:wq :x ZZ save and quit
:q! ZQ quit without saving
i a o start typing (before, after, new line)
dd yy p cut line, copy line, paste
u Ctrl+r undo, redo
/text n N search, next, previous
:%s/a/b/g replace all
gg G :42 first line, last line, line 42
:set number show line numbers
