Skip to content

Unix / Linux - The vi Editor

The vi editor (or its enhanced successor, vim - Vi IMproved) is a powerful, screen-oriented text editor ubiquitous across Unix-like systems. While it has a reputation for a steep learning curve, mastering its basics is invaluable for system administration and development.

Why learn vi/vim?

  • Availability: It’s almost always present, even on minimal system installs.
  • Efficiency: Modal editing allows complex operations with few keystrokes once learned.
  • Resourcefulness: It requires minimal system resources.
  • Power: vim offers extensive features like syntax highlighting, multi-level undo, split windows, and vast plugin support.

This tutorial focuses on essential commands common to both vi and vim. We’ll use vim in examples, as it’s what most users encounter today. If you have vim installed, try running vimtutor for an excellent interactive tutorial.

  • vim filename: Opens filename. Creates it if it doesn’t exist.
  • vim: Opens vim without a specific file.
  • vim -R filename or view filename: Opens in read-only mode.
$ vim my_document.txt

When vim starts, you’ll see the file content (or an empty buffer) with status information at the bottom. Lines starting with ~ indicate they are not part of the file.

Vim’s power (and initial confusion) stems from its modal nature. You are always in one of several modes:

  • Normal Mode: The default mode. Used for navigation, commands, deleting, copying, pasting. Keystrokes are interpreted as commands, not text input. Press Esc to return here from other modes.
  • Insert Mode: Used for typing text directly into the file. Enter Insert Mode using commands like i, a, o. Press Esc to exit Insert Mode and return to Normal Mode.
  • Visual Mode: Used for selecting text (character-wise v, line-wise V, block-wise Ctrl+V). Commands in Normal Mode often operate on the visual selection. Press Esc to exit.
  • Command-Line Mode: Entered by typing : in Normal Mode. Allows executing extended commands like saving (:w), quitting (:q), searching/replacing (:s), setting options (:set). Press Enter to execute the command, Esc to cancel.

Rule of thumb: If unsure what mode you’re in, press Esc once or twice to ensure you are in Normal Mode.

From Normal Mode, use Command-Line Mode (:) commands:

  • :q - Quit (fails if there are unsaved changes).
  • :q! - Quit without saving (discard changes). Use with caution!
  • :w - Write (save) the current file.
  • :w filename - Write (save) to a new file named filename.
  • :wq - Write (save) and then quit.
  • :x - Write (save) if changes were made, then quit (similar to :wq).

Shortcut from Normal Mode (no : needed):

  • ZZ - Save and quit (equivalent to :wq or :x).
  • ZQ - Quit without saving (equivalent to :q!).

Ensure you are in Normal Mode (Esc).

KeystrokeAction
hMove cursor left
jMove cursor down
kMove cursor up
lMove cursor right
wMove forward to the start of the next word
bMove backward to the start of the previous word
eMove forward to the end of the current word
0 (zero)Move to the beginning of the current line (first character)
^Move to the first non-whitespace character of the line
$Move to the end of the current line
ggGo to the first line of the file
GGo to the last line of the file
[N]GGo to line number N (e.g., 10G goes to line 10)
Ctrl+fScroll forward (down) one screen
Ctrl+bScroll backward (up) one screen
Ctrl+dScroll down half a screen
Ctrl+uScroll up half a screen

Many navigation commands can be prefixed with a count (e.g., 5j moves down 5 lines, 3w moves forward 3 words).

CommandAction
iInsert text before the cursor
IInsert text at the beginning of the current line
aAppend text after the cursor
AAppend text at the end of the current line
oOpen a new line below the current line and enter Insert Mode
OOpen a new line above the current line and enter Insert Mode

Remember to press Esc to return to Normal Mode after inserting text.

CommandAction
xDelete character under the cursor
XDelete character before the cursor
dwDelete from cursor to the beginning of the next word
dbDelete from cursor backward to the beginning of the word
ddDelete (cut) the entire current line
d$ or DDelete from cursor to the end of the line
d0Delete from cursor (exclusive) back to beginning of line
d^Delete from cursor (exclusive) back to first non-whitespace char

Combine d with motion commands (e.g., d2j deletes current and next line, df<char> deletes up to next occurrence of <char>). Prefix with a count (e.g., 3dd deletes 3 lines).

Change commands often delete text and then enter Insert Mode.

CommandAction
r<char>Replace the character under cursor with <char> (stays in Normal Mode)
REnter Replace mode (overwrite characters, Esc to exit)
cwChange from cursor to beginning of next word (enters Insert Mode)
cbChange from cursor backward to beginning of word (enters Insert Mode)
cc or SChange (replace) the entire current line (enters Insert Mode)
c$ or CChange from cursor to end of line (enters Insert Mode)
sSubstitute character under cursor (delete it, then enter Insert Mode)

Combine c with motions (e.g., c2w change next two words). Prefix with count (e.g., 3cc change 3 lines).

y stands for ‘yank’ (copy).

CommandAction
ywYank (copy) from cursor to beginning of next word
yy or YYank (copy) the entire current line
y$Yank (copy) from cursor to end of line
pPut (paste) the yanked/deleted text after the cursor (or below current line if line was yanked)
PPut (paste) the yanked/deleted text before the cursor (or above current line if line was yanked)

Combine y with motions. Use counts (e.g., 3yy yanks 3 lines). Note that d commands also place deleted text into the same buffer for pasting.

Using Visual Mode: Enter Visual Mode (v, V, Ctrl+V), select text using navigation keys, then press d to delete, y to yank, or c to change the selection.

  • u - Undo the last change. Vim has multi-level undo; keep pressing u to go further back.
  • Ctrl+r - Redo the last undone change.
  • /<pattern> - Search forward for <pattern>. Press Enter.
  • ?<pattern> - Search backward for <pattern>. Press Enter.
  • n - Repeat the last search in the same direction.
  • N - Repeat the last search in the opposite direction.

Useful settings (use :set command):

  • :set ic - Ignore case during search.
  • :set noic - Case-sensitive search (default).
  • :set hls - Highlight all search matches.
  • :set is - Incremental search (show matches as you type).

To clear search highlighting: :noh (no highlight).

Syntax: :[range]s/search/replace/[flags]

  • :s/old/new/ - Replace first occurrence of old with new on the current line.
  • :s/old/new/g - Replace all occurrences of old with new on the current line (g = global on line).
  • :%s/old/new/g - Replace all occurrences in the entire file (% = range for all lines).
  • :%s/old/new/gc - Replace all occurrences in the file, but confirm (c) each replacement.

From Command-Line Mode:

  • :! command - Execute command in the shell and display output. Press Enter to return to vim. (e.g., :! ls -l, :! python script.py)
  • :r !command - Read the output of command and insert it below the current line.
  • :w !command - Write the file content as standard input to command.

From Command-Line Mode:

  • :set number or :set nu - Show line numbers.
  • :set nonumber or :set nonu - Hide line numbers.
  • :set autoindent or :set ai - Automatically indent new lines.
  • :set expandtab or :set et - Use spaces instead of tab characters.
  • :set tabstop=4 or :set ts=4 - Set tab width to 4 spaces.
  • :set shiftwidth=4 or :set sw=4 - Set indentation width to 4 spaces.
  • :syntax on - Enable syntax highlighting (usually automatic based on file type).
  • :help option - Get help on a specific option (e.g., :help tabstop).

To make settings permanent, add them to your vim configuration file, usually ~/.vimrc.

This covers the fundamentals. vim is incredibly deep; explore vimtutor, the built-in help (:help), and online resources to learn more advanced features.