Stop pressing the up (arrow) to find a previous command
David

David @wulymammoth

About: ☕️ processing unit // self-taught // applied computer science // I code for fun // sports fanatic (NBA, NFL) // hip-hop // sneakers // fueled by imposter-syndrome

Location:
san francisco, ca
Joined:
Jun 22, 2020

Stop pressing the up (arrow) to find a previous command

Publish Date: Jul 11 '20
93 21

Ever wonder if there are ways to be more efficient in our terminal and shell? Feeling a little clunky? Here are a few good-to-knows for those of us that have never dabbled in sys-admin or dev-ops work


problem : Do I have to push up (arrow) multiple times to find a previous command that I need to run? What if I just want to run the last command again?

solution : Please, for the love of anything, stop (pressing up multiple times and eyeballing)! This is ridiculously inefficient! Three things!

-- FIRST -- To simply run the previous command without moving off our keyboard's home row: ctrl-p (mnemonic for "previous") followed by the <Enter> key. Went past our command? ctrl-n (mnemonic for "next").

-- SECOND -- If we know it's not the last command, the following is probably the utility that I rely on most: reverse-i-search. This utility treats our (command) history like a stack and (fuzzy) finds the most recent match for any term/keyword that exists in our history. To initialize it, hit ctrl-r. Once we've typed something it should arrive at our first match. If the first match isn't what we're looking for, then hit ctrl-r again and it'll go to the next previous match. And if we've gone past it, use ctrl-s/<Shift>-ctrl-r (depending on our operating system). To exit the search, use ctrl-g. This has almost completely eliminated all my use of aliases.

Let's say that our history looks like this. NOTE: the numbers on the left correspond to the line number in my bash history

$ history
2311  ls -l
2312  rg --files | fzf
2313  vim reverse_singly_linked_list.py
2314  python -m unittest reverse_singly_linked_list.py
2315  ping google.com
2317  mix routes
2318  mix phx.routes
2319  git branch
2320  git log -3 --reverse
2322  htop
2326  jobs
2327  git status
2328  git diff -w
2329  ./deploy.sh
2330  less README.md
2331  man awk

Now, I'm at my prompt and I'm searching for the last command that contained the following characters: test. If we eyeball above, we'll notice that it's command number 2314 that corresponds with a unit test that I ran with Python for a linked list. What most people do is press up twelve, I repeat, TWELVE, times! When hitting ctrl-r, followed by entering the characters, test, will find that command in its entirety. We can just hit <Enter> to invoke (run) it

                     👇 # what we type will display here
$ (reverse-i-search)`test': python -m unittest reverse_singly_linked_list.py
                                          👆 # match begins here

-- LASTLY (third) -- we can "pipe" our history into grep (without the angle brackets). This will pull up ALL matches of a command that contains the given term. This is useful if we can only remember some fragments of a command AND to avoid having to hit ctrl-r many times when there are multiple matches.

$ history | grep <term/keyword(s)>

problem : What are the options for this thing? (some Unix utility) Do I have to go to Google every time?

solution : built-in Unix utilities (i.e. ls, cd, rm, xargs, ps) typically have many options. One of the quickest references available is the manual, also known as man-pages, that can simply be invoked with $ man <utility>, (e.g. $ man ls). I've found ls -l (long format), ls -la (long with directories), and ls -lt (long ordered by time) to be particularly useful.


problem : Okay, so I'm now using man-pages, but how do I navigate this thing or find what I'm searching for? This thing is massive!

solution : man-pages typically adopt vi movements (popular text editor found on almost all Unix/Linux-based machines including macOS). They can simply be searched by first hitting the / (forward slash) to initiate a search, followed by some keyword or option (e.g. /foobar or /-a) will search for foobar or -a within the page.


problem : Okay, so that search only takes me to the first matching instance. How do I find the next one? Or go back to the previous one?

solution : We can use n (lowercase and mnemonic for "next") to go to the next instance, and <Shift>-n (capital) to go back (to the previous instance)


problem : Is there a way to make a new directory and switch into it immediately?

solution : $ mkdir foo && cd $_. The last command argument is captured in the _ (underscore) variable. To access variables, we use the $ prefix


problem : Is there an easier way to switch back and forth between directories?

solution : Use -

$ pwd
/Users/me/Desktop

$ cd foo
foo $

$ pwd
/Users/me/Desktop/foo

$ cd -
/Users/me/Desktop

$ cd -
/Users/me/Desktop/foo

problem : How do I move around the text for a command that I've already typed or edit a previous command? How do I go to the beginning of the line or the end of the line?

solution : readline shortcuts - allow us to navigate within a line and perform edits. This is a huge efficiency gain. Surprisingly, most of our tools are built with readline, so these typically work in any place that allow us to type text (i.e. Chrome or Firefox address bar, Google Doc, etc) so they are worth learning even outside of a shell

Try these out. NOTE: on macOS, we must configure the meta keys for the option-key-based commands to work (how-to after the commands below). If we care about ergonomics a common key re-map is changing our caps-lock key to ctrl. This can be done through our system keyboard preferences' modifier keys (on macOS):

alt-b / option-b (macOS): move cursor back one word
alt-f / option-f (macOS): move cursor forward one word
ctrl-a: move cursor to the beginning of line
ctrl-b: move cursor backward (←)
ctrl-d: delete a character
ctrl-e: move cursor to the end of line
ctrl-f: move cursor forward (→)
ctrl-k: kill the line after the cursor, add to clipboard
ctrl-n: next line, next command in history (↓)
ctrl-p: previous line, previous command in history (↑)
ctrl-u: kill the line before the cursor, add to clipboard
ctrl-w: delete a word
ctrl-y: undo / paste from the clipboard

HOW-TO set up meta keys for forward and backward using option keys in iTerm2 on macOS:

  1. Go to Profile > Keys
  2. Load Preset > Natural Text Editing
  3. Switch Left/Right Option from Normal > Esc+

Comments 21 total

  • Filipe Reis
    Filipe ReisJul 12, 2020

    Or just use the UP key

    • Osaid
      OsaidJul 12, 2020

      Well, that's still an option.😂

    • David
      DavidJul 12, 2020

      When you’ve reached rock bottom, there’s no place to go but up 🙃

  • jgarr16
    jgarr16Jul 13, 2020

    Thanks for the post, David. I found some useful tid-bits here; like using "cd -" in bash to bounce back & forth between directories; who knew? Also, the readline shortcuts - I've used them on the command line for a while, but didn't know that they worked elsewhere - hate to think how many times I could have used "control-k" for URLs.

    • David
      DavidJul 13, 2020

      Yah! It's great! I also like to remove segments of the path in the URL up the previous forward-slash using option/alt-backspace. I'm a little more inclined because I'm big on keyboard shortcuts so I always search for ways to do things in an application without the mouse

  • ProDigit
    ProDigitJul 13, 2020

    Why make it more difficult, to search back and forward?
    Ctrl p and ctrl n, is more difficult than up/down.

    • David
      DavidJul 13, 2020

      You're not wrong, ProDigit. On most keyboards, it's a bit of a stretch to reach for the left ctrl with one's pinky. You'll have to decide for yourself whether this is more difficult than moving your entire right hand off the home row of your keyboard to the arrow keys unless you've remapped. What if you need to edit the previous command? Your hand is now oscillating between your jkl; keys and the arrow keys. I'm often modifying the argument to my previous command either because I made a typo or I when I need to edit it

      $ gt commit -am WIP
      -bash: gt: command not found
      

      Many will perform the following sequence of actions:

      1. move hand off onto arrow keys
      2. press the up arrow
      3. hold the left arrow until arriving at the letter t, maybe miss it because key-repeat was cranked all the way up to adapt to these slow scenarios (especially for typos in long commands)
      4. type the letter i
      5. hit enter

      Alternatively...

      1. ctrl-p
      2. ctrl-a
      3. option-f
      4. ctrl-w
      5. type git
      6. hit enter

      One additional step, but I can almost guarantee that this is faster and more precise than less keys and trying to eyeball and correct for inaccuracy

      Lastly, this is actually far easier for a subset of us that are touch typists, but we typically also have some or all of the following configurations:

      • caps-lock is mapped to ctrl (to reduce the pinky reach) as it's a fairly useless key (like really used less frequently than almost any other key on the keyboard)
      • I have a 60% keyboard which does not have arrow keys at all, but this is a trade-off I've made for portability

      If you've read beyond the first tip, everything that I've mentioned is about efficiency in one's terminal and shell, but use your own discretion.

      • ProDigit
        ProDigitJul 13, 2020

        I don't know. Click 3 times up, and then enter,
        Or click multiple times ctrl + p and then enter.
        Arrow keys also are faster when you need to modify the command. You can immediately go to the end, middle or beginning with left/right arrows right next to it.
        I prefer the arrows, and for anything else ctrl + R.
        The only way I would consider something else than the arrows, is if I'm running a pet or c64, without direct arrow keys (there you still have to press shift + arrow).

        • David
          DavidJul 13, 2020

          Just another tool in the box. I'm not opposed to arrow keys at all. my hjkl keys are are my arrow keys, but requires me to depress the function key to activate and do, at times, rely on it, particularly in applications where these readline key combos don't work.

          Did you just name drop C64 as in Commodore64? Are we diggin' 'round the attic for antiques?

  • FreeSoftwareServers
    FreeSoftwareServersJul 13, 2020

    I recently found out about using ! (exclamation) and them previous beginning of command. Eg: "!ssh" will run last command in your history that started with ssh. And I love the tip below about "cd -".

    • David
      DavidJul 13, 2020

      I've certainly forgotten about this one! Thanks!!

  • Rodrigo Graça 👨🏻‍💻🐛
    Rodrigo Graça 👨🏻‍💻🐛Jul 13, 2020

    I can see you still use Bash.....
    poor kid... I feel for you 😢 😂

    1. You can use !! to get the last command really quick. or !cat to run the last command that started with cat
    2. You can press the up arrow and move your right hand up and press Home to go to the beginning of the line way faster than pressing "command-f" not to mention that its Mac specific 🤮.
    3. You can use CTRL + LEFT/RIGHT (maybe its Option for you Mac users) to skip one entire word. 😍 It works for all programs and OSs. Not only your terminal. And I mean ALL!!!! Same goes CTRL + HOME/END
    4. If you used ZSH (instead of Bash) you don't even need to know a given command was your last, you can get anything from your history really quick by starting to type it and then accepting the autocomplete with a RIGHT arrow click. I use this so often! I know I have used scp in the past so I just start writing scp hit RIGHT and it literally types 102 characters for me instantly. (note: this is a plugin called "zsh-autosuggestions") (btw, if you are on a Mac🤮😂 why are you on bash? didn't they switch? you didn't update your Mac? 😮😱)
    5. If you are using VS Code install Cameron.rerun-last-command and then You can just press CTRL + 7 again and again, to do !!. Thank me later 😂
    • David
      DavidJul 13, 2020

      You do realize that zsh is not installed on remote machines. Right? Are you familiar with the differences between zsh and bash and the subtle idiosyncrasies? Probably not, but they matter. I work on remote machines that don't have zsh, silly.

      I'm a little insulted by your assumptions. I actually do use zsh on a different machine (it's the default on new Macs), but I've also used it in the past along with oh-my-zsh, Prezto (for a long time ~5 years), and fish (short time).

      1. Sure. How is that different from up or ctrl-p and the requirement on two keys? Can, but do you? The ! commands, by default, don't provide a visual indication of that last command, so you're running it blindly, so it's utility is diminished

      2. I can't help but laugh. Do you know why? You completely misread. None of these commands are Mac-specific. And where is the "command" key mentioned? I just mention option/alt (alt for non-Mac). But anyway, carry on. Not everyone uses a 100% or 150% keyboard like yourself and packs a mouse when traveling. But, go ahead, bring your desk, too. While you're at it, maybe a floppy disk with all your dependencies in case there isn't wifi. I have a 60% keyboard that is portable for travel. It doesn't have home, end, or arrow keys. Wait. Did I mention readline shortcuts? Oh, I did! Did you read? No. They are not Mac-specific. I still have a PC with both Windows and a Linux distro on it. While you're over there moving your hand off the keyboard searching for your home, end, and arrow keys, and greeting your home row again, I'm pressing ctrl-a (beginning of line) and ctrl-e (end of line). LOL! Silly silly, you. Again, I would advise you to read before you make remarks like this. Your lack of reading shows -- didn't I say that readline shortcuts are not terminal and bash-specific? Nor are they Mac-specific. Go ahead, I'm waiting... for you to give yourself a face palm...

      3. Again. Read my post in its entirety -- same as point 2 that I'm making... readline shortcuts.

      4. If you use Windows instead of a terminal, you don't even need a keyboard! Why type text when there's a GUI? See the hilarity in how you make assertions? Well, damn. I didn't know this. I've never used zsh 🤷‍♂️. You must have many friends. I can see the dependencies bleeding into your life -- plugin this; plug in that; plug a floppy disk with zsh into the remote connection... Are you familiar with the Unix philosophy? It's worth a read. I avoid having more plugins than I need. I'm not telling people what to use (despite the title/clickbait). I'm just providing options that are nearly universal across platforms. zsh is not the default shell on every Linux distro. zsh is DEFINITELY more convenient. And the way that you use zsh is slower compared to me. ctrl-r, type command, and enter as you dance between sets of keys. Bless you, child! (see what I did here? I inverted our relationship). The visual auto-completion is nice. I miss that when I'm not on my machine with zsh.

      5. Yeah, you should really read before you comment. LOL. I don't use VSCode. I use Vim. You're bleeding, "I'm way cooler than you" attitude which I'm sure makes you many friends.

      Lastly, I'm already certain that I'm slower in my shell than you are and I only type one word per minute, because why be in such a rush when enjoying life on a beach? Speed kills. I'd rather slow down and experience it :)

      • Rodrigo Graça 👨🏻‍💻🐛
        Rodrigo Graça 👨🏻‍💻🐛Jul 13, 2020

        Seems someone didn't catch my jokes.
        (Even with my heavy emoji usage 😅)

        I guess I have to work on that. 🤭😂

        • David
          DavidJul 13, 2020

          Oh, I caught them... but they're not jokes. They're what is called, "back-handed" comments. If you had acknowledged or were aware of the alternatives as I've mentioned, then you likely would have mentioned them... but anyway, I'm sure that you learned a thing or two, even if you fail to acknowledge them or should I say, "my jokes"? ;)

  • Soumya Prakash Parida
    Soumya Prakash ParidaJul 13, 2020

    Unless you are writing a new OS every month, what's the hurry?
    Enjoy the scroll 😄

    • David
      DavidJul 13, 2020

      No hurry...as I ask Alexa to scroll for me while I have my feet up on the table and sip on my coffee and watch the birds sing ;)

  • Gauthier
    GauthierJul 13, 2020

    Or use a more powerful shell like fish 🐟😉

    • David
      DavidJul 13, 2020

      Sorry, I'm a Prezto user (on my other machines) ;)

      However, this obviously discounts the availability of zsh on remote machines... where I sometimes do work

  • Scott
    ScottJul 14, 2020

    Thanks for sharing! Just used ctrl-p!

  • Ray Luo
    Ray LuoJan 8, 2024

    Great article! Learning the ctrl-p brings so much joy to me!

    One more thing. If you are already a vim user (and the OP is), and if you already spend most of your time in vim writing code, you may just type all (non-daemon) commands inside vim by using :! prefix, such as :!echo hello world. Later you can type q: in vim to open a history of all shell commands that you used inside vim, and use all the native vim ways to navigate (h, j, k, l, w, b, etc.), and edit inline, then hit enter to run it.

Add comment