Skip to main content

An important and sometimes overlooked skill is mastering the command line. Being proficient on the command line can save a lot of valuable time during those practical exams such as the RHCSA and RHCE – especially considering the slow KVM console used during those exams. Have you ever seen this scenario while watching a technical video?

The instructor makes a mistake on a command, presses arrow-up to recall the previous command, and then holds arrow-right down until the cursor is somewhere near where edits need to be made. He then carefully moves the cursor to just after the edit point, and backspaces over the mistakes, only to re-type the correction.

It is slow, painful to watch, and simply not necessary.

This guide will demonstrate how to put your shell in “vi” mode, and how to take advantage of it.


How do we get started?
By default on Red Hat / CentOS systems, the bash shell is in “emacs” mode. The shell can either be in this mode, or in “vi” mode, but not both. It’s also possible to turn them both off; however this breaks things like using the arrow keys to cycle through previous commands. This is because there is nothing to interpret the escape sequences from the key strokes. Use the set command to determine the current mode, or to set a new mode. Here is an example:

$ set -o | egrep -w "emacs|vi"
emacs on
vi off
$ set +o emacs # Turns off emacs mode.
$ set -o | egrep -w "emacs|vi"
emacs off
vi off
$ ^[[A^[[A # Cursor up doesn't work now.
$ set -o emacs # Emacs mode back on.
emacs on
vi off
$ set -o vi # vi mode on. This also turns emacs off.
$ set -o | egrep -w "emacs|vi"
emacs off
vi on

This change will only persist for the duration of the current shell. To make the change persistent for all future shells for this user, edit the .bashrc file in the user’s home directory, and add set -o vi as a new line in the file.

EXAM HINT: As the root user, edit /etc/bashrc, and add set -o vi to the end of the file. This will make the change persistent for all future shells for all users, including root.


VI has 3 modes: vi mode, input mode, and command mode. We’re mostly interested in vi and input mode. However, one of the most interesting things that can be done with command mode is “search”. Once you are comfortable with using this feature, it is generally faster than using fc -l [number] and ![number] to look through and re-execute a command within the shell history – especially for lengthy shell histories where grep might also be required.

To use the vi search feature, press <ESC> to make sure you are not in vi input mode. Press /, type in your search string, and then press <ENTER>. Vi will populate the command prompt with the most recent command in the shell history that matches the search criteria. If there is no match, the terminal will beep, and nothing will be returned. Assuming there is a match, press <ENTER> to execute that match. If that particular match isn’t what is desired, another VI feature can be used to scroll through all matches. Press n to scroll up through previous matches, and N to scroll back down. For example, assume this as part of the shell history:

$ fc -l
17 this is 1
18 this is the command I want
19 this is 3

Press <ESC> to make sure you’re not in vi mode. Press / to enter vi search mode. Type this, and press <ENTER>. The CLI should return:

 $ this is 3

Press n. The previous match in the shell history is now displayed.

$ this is the command I want

Once the desired command is displayed, simply press <ENTER> to execute it.

Another lesser known but useful trick is using the v command when editing a command on the CLI. This will invoke the vi editor as if you ran the vi command, but the current contents of the command line will be loaded. Make edits as desired, and then upon exiting vi, the contents will execute. It’s especially useful for editing multi-line scripts, or complex commands involving pipes, grep, awk, etc. To demonstrate this feature, login as root, and paste these three lines:

for x in {1..5} ; do
useradd user$x

If everything works as expected, user1 through user5 will be created. Now lets quickly construct a command to delete those same 5 users. First, recall the last command. There are several ways this can be done, including the vi search feature described above. For example, Press <ESC>, then /, then type a search string. In this case, “useradd” would work well. Another option is arrow up. As mentioned before, in vi mode, the escape sequences generated by pressing the up-arrow key are correctly interpreted. However – vi gives us yet another way: <ESC>+k. That will recall the previous command. Press <ENTER> to execute the command. Alternatively, continue pressing k to cycle backwards through the shell history. If you inadvertently go too far, press j to cycle forwards through the shell history.

NOTE: Using <ESC>+k may seem a bit awkward at first, but other flavors of UNIX such as AIX do not have any native support for using the arrow keys to navigate shell history. Therefore, <ESC>+k is far more utilitarian by comparison in those types of environments.

Regardless of the method chosen for recalling the last command, the result should look something like this:

# for x in {1..5} ; do useradd user$x; done

Press v. The vi editor will open, and the command will be loaded into it. Change “useradd” to “userdel -r“, and press <ESC>+:wq. The command will execute, and it should delete user1 through user5.

TECHNICAL NOTE: If you do not want to execute the contents of the vi session, exit vi with <ESC>+cq.

The usefulness of using the v command may not be immediately apparent. However, once you begin using more complex commands and in-line scripts, this trick should find a home in your repertoire.


It is fairly straight forward to find vi cheat sheets online. However, to a new vi user, it can seem overwhelming, and it’s not always clear what is useful in different circumstances. Master a basic set of navigation and edit commands, and you should pretty quickly figure out those time-saving techniques for CLI mastery that can make or break passing a hands-on Linux exam.

Lets start with an example that is both practical in the corporate environment, as well as in the RHCE exam: NIC teaming.

First, build the team device.

NOTE: There is a deliberate misspelling for the exercise of using vi.

# nmcli con add type team con-name team0 ifname team0 confg '{"runner": {"name": "activebackup"}}'
Error: invalid <setting>.<property> 'confg'.

Press <ESC>+k to recall the previous command. The cursor will be at the beginning of the line, and you are in vi mode. The goal is to correct the misspelling of “confg” to “config”, and re-execute the command.

Lets start with a few vi navigation commands.

w and b move the cursor forward and backwards by one “word”.

$ and 0 (zero) move the cursor to the end and beginning of the line.

l and h move the cursor forwards and backwards by one character.

NOTE: If your terminal emulation supports arrow-left and arrow-right, they work just as well as l and h.

Get used to those word navigation keys, and get an idea of what constitutes a word separator character. For example, _ (underscore) is not a word separator. However, (hyphen) is.

Use those navigation keys to move the cursor to the c in confg.

As with most things UNIX, there are many ways to make the correction to confg. Here are some examples that introduce some additional vi features:

– Type dw (delete word), then i (enter vi insert mode). Type config. Press <ESC> (exit vi insert mode).

– Press h until the cursor is on the g in confg, type i (enter vi insert mode), and then type i again (inserts i into confg). Press <ESC> (exit vi insert mode).

– Type cw (change word). All characters up to the next word separator get deleted, and vi is in insert mode. Type config. Press <ESC> (exit vi insert mode).

Press <ENTER> to execute the command. It should work correctly now.

Move on to the next command needed for NIC teaming: adding a team-slave connection. Press <ESC>+k to recall the previous command. The first 4 words are correct for the next command, but the rest of it is not.

# nmcli con add type team con-name team0 ifname team0 config '{"runner": {"name": "activebackup"}}'

Press w 4 times. This will put the cursor on the word team. Now press D (delete to the end of line). Press i (enter vi insert mode). Type the rest of the command, and execute it. It will look something like this:

# nmcli con add type team-slave con-name team0-port0 ifname eth0 master team0

To add the second interface in the NIC team, use the exact same command as before, except with 2 character substitutions. Here is one way of doing it, with a few more vi commands introduced too:

1. Press <ESC>+k to recall the last command, and press w until the cursor is on the I in ifname.

2. Press h twice, leaving the cursor on the 0 in port0.

3. Press r (replace 1 character), and then type 1 (automatically returned to vi mode).

4. Press w until the cursor is over the e in eth0, and then press l until the cursor is over the 0.

5. Press r, and and then type 1.

Press <ENTER> to execute the command, which will look like this:

# nmcli con add type team-slave con-name team0-port1 ifname eth1 master team0

At this point, nmcli con mod team0 would be used to configure the IP, mask, and gateway, etc. To finish out the NIC teaming example, here are a few more vi editing tricks.


# nmcli con up team0

Press <ESC+k> to recall that last command. Replace team0 with team0-port0. The following methods all accomplish the task:

w over to team0, use cw (change word) and type team0-port0.

w over to team0, press R (replace mode), and type team0-port0.

– Press A (append mode at the end of the line), and type -port0. If there happens to be a space after team0, then instead of immediately typing -port0, press <ESC> (exit vi input mode), and press x (delete 1 character). Then press A again, and type -port0.

Press <ENTER>, and move on to bringing the last connection up. Press <ESC>+k to recall the last command.

# nmcli con up team0-port0

Press $ to go to the end of the line, then press x until the 0 in port0 is deleted. Press a (append after the cursor), and type 1. That should result in this command:

# nmcli con up team0-port1

NOTE: If during the course of editing a command, you lose track of whether vi is in insert mode or not, or just make a typing mistake and want to start over, press <CTRL>+c. It will immediately return to an empty command prompt, and vi is once again in command mode.


In summary, the Linux bash shell can be enhanced by turning on vi mode, either temporarily by typing set -o vi at the command prompt, or more permanently by adding it to a user’s ~/.bashrc, or even globally by adding it to /etc/bashrc.

In vi mode, we gain new functionality such as:

/ for searching shell history.

<ESC>+k as an alternate method for scrolling through shell history.

v for invoking the vi editor with the current shell command pre-loaded for editing, with execution after exit.

Plus, we can boil down vi to a dozen or so different commands instead of a lengthy cheat sheet that can be overwhelming:

w and b move the cursor forward and backwards by one “word”.

$ and 0 move the cursor to the end and beginning of the line.

l and h move the cursor forwards and backwards by one character.

cw to change a word, and dw to delete a word.

r to replace a character, and x to delete a character.

i to insert text at the cursor, a to append text after the cursor, and A to append text at the end of the line.

– Press <ESC> to exit vi input mode.

– Press <CTRL>+c to break out of editing the current command, and return to a fresh command prompt.

Learning vi integration with the shell using this abbreviated list of commands can save a considerable amount of time, both in the corporate world, and during practical exams where time is at a premium.

Comments are disabled for this guide.