Become a Command-Line Ninja with These Shortcuts

May 05, 2019

I’ve often found myself in such a frustrating situation, where I have to replace one keyword in the middle of a looong shell command that I just copied and pasted into the terminal (from StackOverflow or course 😅). Jumping over words with Alt-Arrow doesn’t work on all machines; how many left arrows and backspaces do I have to press, in order to replace that path/to/file or username in that genius command I stole from that SO answer??

Finally, I sat myself down to do some research on how to properly practice Ninjutsu in the terminal. As it turns out, roaming inside that command line environment is not that difficult at all!

I’m primarily a Z-Shell user, so this article will be more focused on ZSH. The shortcuts we are going to see here, however, should mostly work in BASH as well (sorry I don’t use FISH or other shells ).

Fun fact: shell key bindings actually defaults to “emacs mode”! You may have already discovered this if you are an emacs user. But for us mere mortals (or VIM-mortals), let’s carry on and learn something new!

In fact, if you are more comfortable with VI/VIM, you can even switch to VI-bindings from the standard emacs one - use set -o vi to test it out! (You might need a plugin or two to give you hints whether you are in edit or normal mode though. Oh-My-Zsh has a plugin for this!)

Let’s jump right in with the navigation shortcuts. Here’s a little list of the useful ones:

Shortcut Action
Ctrl-A Jump to the beginning of line
Ctrl-E Jump to end of line
Ctrl-B Move back by one character
Ctrl-F Move forward by one character
Meta-B Jump back by one word
Meta-F Jump forward by one word

Note that what the Meta key actually is may vary on different setups (OS + terminal simulator). You might find Alt working on your system as the Meta key, or the Command key (if you are using iTerm on macOS, you can change Meta key binding in “Preferences”). However, if all fails, try pressing ESC then release (not using it as a modifier), followed by the other key - this should work universally as well.

Editing

Here’s a little list of default key bindings for editing:

Shortcut Action
Ctrl-U Cut current line*
Meta-W Cut everything before the cursor (multi-line!)
Ctrl-K Cut everything after the cursor on current line
Ctrl-W Cut the previous word
Meta-D Cut the next word
Ctrl-Y Paste the stuff just cut (doesn’t use OS clipboard)
Ctrl-_ Undo last change

* This shortcut cuts everything before the cursor in BASH.

I never knew that I can undo in the terminal! How do you undo on Android BTW? 🤨

Searching and History

Something you might not know is that shells default to log every command that you’ve ever executed if you didn’t opt out. For ZSH, that log book is kept under ~/.zsh_history (or ~/.bash_history for BASH). This is actually a pretty neat feature, allowing us to search from previous commands and reuse them anytime to save time. (If you are feeling like to go incognito, you may wanna set HISTSIZE = 1 in your .zshrc to limit the history storing to only 1 record. HISTSIZE = 0 doesn’t seem to work though.)

To enter search mode, press Ctrl-R. Now type the keyword that you are looking for. Press Ctrl-R again to “find next”.

You can exit the search mode anytime by trying to edit the current displaying search result, directly with the shortcuts we’ve mentioned above. Of course, you can abort with Ctrl-C as well!

To iterate through the previous commands though, we don’t need to enter search mode - just use Ctrl-P to show the p-revious, or Ctrl-N to show the n-ext line!

More Cool Stuff

Instead of the clear command, shortcut Ctrl-L is another way to clear the screen. It also leaves the line you are working on intact, so if you are in the middle of typing a long command but suddenly find the littered terminal screen is super distracting, you can hit Ctrl-L to clean up, without having to retype the command.

Ever wanted to type multiple lines into ZSH then execute in one single setting, just like copy & pasting some multi-line shell snippets? Ctrl-V Ctrl-J will do the trick! (Ctrl-V is “quoted-insert”, which inserts instead of interprets the next input; Ctrl-J prints the ASCII symbol LF, the Unix “next-line”.)

Even Cooler - DIY! 😋

In ZSH, you can always obtain a list of the current key bindings with a simple bindkey command. A BASH equivalent would be bind -P.

In addition to the ability of switching to VIM mode, if are using ZSH and would like to customize your key bindings, you can easily do so by declaring stuff like bindkey "^[X" zle-command (zle, The Z-Shell Line Editor is the line editor behind our beloved ZSH). A list of zle-commands can be obtained with zle -al.

I hope you have enjoyed this post, and have learned something useful, my fellow ninja! 🥳