Dr Hjkl on the Command Line


The first time I used vi was in a college programming course. It was the default editor on the computer lab's UNIX systems we used to compile our assignments. I remember when our professor first introduced vi and explained that you used the hjkl keys to move your cursor around instead of the arrow keys. Before this point, I was a pico user (that dates me a bit now), and it seemed so backward to me that vi used hjkl instead.

It wasn't until I became a heavy vim user that I began to appreciate the speed you gain from navigation keys appearing on home row. As a touch typist, I realized the arrow keys are in a no-man's land outside the home row compared to hjkl, and even though vim supported arrow keys, I used hjkl instead. I've been pleased to discover a number of different programs that also support the same level of key bindings.

I've written a few other columns in Linux Journal through the years along those lines (all with Dr Hjkl in the title), and here, I've decided to revive Dr Hjkl for another round of time-saving command-line navigation tips that will help keep your hands on the home row and off those arrow keys.

Most of my tips in this article are about reducing your reliance on the arrow keys and increasing your speed when on the command line. For many years, whenever I would find a mistake in a command I typed, I would do one of two things: use a combination of Home, End and the arrow keys (all way too far away from home row) to move the cursor back to the mistake so I could fix it, or sometimes I found it was faster to press Ctrl-C and type the whole command again. One day I observed another Linux user fly back and forth across words on the command line and realized there was a better way.

Moving Between Words

The first simple speed improvement is the use of Alt-b and Alt-f to move backward or forward one word on the command line. This behaves somewhat like the b and w keys in vi to skip between words instead of one letter at a time. Alt-b acts like just like b in vim. Press Alt-b, and the cursor will move back one word and sit at the first letter of the previous word. Alt-f is slightly different; the cursor moves forward until it ends up at the space between words instead of at the beginning of the following word. So given the following command:

ls -l /var/log

If my cursor were at the end of the line and I pressed Alt-b, it now would be over the l in log. If I pressed it again, it would move to the v in var. If my cursor were at the beginning of the line and I pressed Alt-f, it would end up on the space between ls and -l. This annoys me enough that often I'll find myself going forward an extra word and then pressing Alt-b so the cursor is where I want it. Even though it's more keystrokes than the right-arrow key, it keeps my hands on the home row. Alternatively (as you'll see later), I simply could press Ctrl-f to move forward an extra letter instead.

Delete Words

The bulk of the time that I use Alt-b and Alt-f on the command line is to correct a typo earlier in the line. Now, you certainly could move the cursor over to the right position and then use Delete or Backspace to erase the error, but for minor mistakes, I've found it's much faster to delete the whole word and retype it. In vim, I would type cw to change the word under my cursor, or a slightly slower approach is to type dw to delete the word and then enter insert mode to make my changes. On the command line, you can replicate the behavior of dw with Alt-d. The Alt-d key will remove the word under the cursor completely so you can retype it. So, taking the same example from above:

ls -l /var/log

If my cursor were at the end of the line and I realized I wanted to change -l to -ltr, I would press Alt-b three times to move it over the l in -l, then I would press Alt-d to delete the l, and finally type ltr.

Replace Home and End

It turns out the arrow keys aren't the only ones on the hit list. Home and End, although useful, also are out in that no-man's land away from the home row. In vi, you would just use ^ or $ to go to the beginning or end of the line. On the command line, you can replace Home and End with Ctrl-a and Ctrl-e, respectively. If you use screen or tmux with screen key bindings, you know that Ctrl-a already is called for, so you'll need to press Ctrl-a a to send that Ctrl-a through to the command line. Ctrl-a can be particularly useful when you realize you need to pipe some initial command through something you've already typed, and Ctrl-e is useful to move back to the end of the line afterward to finish your command after editing it somewhere in the middle.

A Few Final Shortcuts

Although the above shortcuts are enough to get started, before I finish, I want to highlight a few extra shortcuts that are less useful but worth knowing all the same. First, although Alt-b and Alt-f move backward and forward a word, respectively, their counterparts Ctrl-b and Ctrl-f will move backward and forward a single letter. Somewhat less useful, but still interesting, is the fact that you can use Alt-u to uppercase the full word under the cursor, Alt-l to lowercase the word, and Alt-c to capitalize the first letter in the word.

With all of these tips, I recommend posting a reminder to yourself somewhere on your computer. It may take a few weeks to ingrain a new habit like this into your command-line use, but once you get used to it, you won't go back. I've found that these shortcuts also apply in command-line clients like Irssi, so if I notice I have a typo in something I'm about to say in IRC, I can just press Alt-b until it's under the cursor, and press Alt-d to delete it, and then correct the error and press Enter.


Kyle Rankin is VP of engineering operations at Final, Inc., the author of many books including Linux Hardening in Hostile Networks, DevOps Troubleshooting and The Official Ubuntu Server Book, and a columnist for Linux Journal. Follow him @kylerankin