Quick Answer

The shell uses readline key bindings by default, so the same shortcuts work in bash, zsh and tools like the Python REPL and psql. The high-value ones: Ctrl+R to search history, Ctrl+A and Ctrl+E to jump to the start and end of the line, Alt+B and Alt+F to move by word, Ctrl+W to delete the previous word, Ctrl+U and Ctrl+K to cut to the start or end, and !! and !$ to reuse the last command or its last argument.

Move around the line without arrow keys

Holding the left arrow to crawl back to the start of a long command is the slowest thing you do in a terminal. The shell reads these keys instead:

  • Ctrl+A: jump to the beginning of the line.
  • Ctrl+E: jump to the end.
  • Alt+B: move back one word.
  • Alt+F: move forward one word.
  • Ctrl+B and Ctrl+F: move back or forward one character.

These come from the readline library, which bash uses by default and which zsh mirrors in its default (emacs) editing mode. The same keys work anywhere a program uses readline or libedit: the python and node REPLs, psql, irb, gdb. Once the movement keys are muscle memory you stop thinking about where the cursor is, which is the point. On some keyboards the Alt combinations are sent by the Option or Meta key, or by pressing Esc and then the letter.

Delete and recover text

Editing instead of retyping:

  • Ctrl+W: delete the word before the cursor, splitting on whitespace. Good for removing the last path you typed.
  • Alt+Backspace: delete the previous word, but splitting on punctuation too, so it stops at /, - and .. Use it to remove one path segment.
  • Ctrl+U: cut from the cursor to the start of the line. In bash this is to the start; in zsh's default it cuts the whole line.
  • Ctrl+K: cut from the cursor to the end of the line.
  • Ctrl+Y: paste (yank) the last thing you cut. Alt+Y cycles through earlier cuts.

The cut text goes to the shell's own kill ring, which is separate from your system clipboard. So Ctrl+U to stash a half-typed command, run something else, then Ctrl+Y to bring it back, all without touching what you copied from the browser. That stash-and-restore move is worth learning on its own.

Ctrl+R starts a reverse search through your command history. Type a few characters from any part of a past command and the most recent match appears. Press Ctrl+R again to step to the next older match, Enter to run it, or Ctrl+G (or Ctrl+C) to cancel and keep your current line. Pressing the right arrow or Ctrl+E drops the match onto the prompt so you can edit it before running.

This replaces almost all of the retyping people do. Instead of remembering the exact docker run line with six flags, search for docker run and pull it back. history prints the numbered list, and !123 re-runs entry 123.

If you run several shells at once and history feels incomplete, that is because by default each shell writes its history when it exits. Setting the shell to append after every command fixes it, and is worth doing early.

History expansion: !! and friends

The shell expands ! patterns before running a line. All of the following were verified in bash:

  • !! is the previous command. sudo !! re-runs it with sudo after a permission error.
  • !$ is the last argument of the previous command: mkdir -p a/b/c then cd !$.
  • !* is all arguments of the previous command; !^ is the first.
  • !git runs the most recent command starting with git.
  • ^old^new re-runs the last command with the first old replaced by new.
  • !!:gs/old/new/ re-runs it, replacing every old with new.

A cleaner alternative to !$ is Alt+. (or Esc then .), which inserts the last argument of the previous command straight into your line, and repeating it cycles back through the last arguments of earlier commands. The shell variable $_ also holds the last argument, so mkdir build && cd $_ works inside scripts where history expansion is off.

Small ones that add up

  • Ctrl+L: clear the screen but keep whatever you have already typed on the line. The clear command clears the screen too, but runs as a command, so it does not preserve a half-typed line.
  • cd -: switch to the previous directory. Run it again to switch back. cd with no argument goes to your home directory.
  • Ctrl+X Ctrl+E: open the current command line in your $EDITOR, for building up a long pipeline comfortably. Save and quit to run it.
  • Ctrl+_: undo the last edit on the line. Repeat to keep undoing. Some terminals send this on Ctrl+/ as well.
  • pushd and popd: keep a stack of directories instead of a single previous slot; dirs shows the stack.

Brace expansion is not a keybinding but belongs here: cp config.yml{,.bak} makes a backup in one step, and mkdir -p src/{api,web,shared} creates three directories at once.

Frequently Asked Questions

Do these shortcuts work in zsh and on macOS? Yes. macOS ships zsh, and its default editing mode uses the same emacs-style bindings as bash: Ctrl+A, Ctrl+E, Ctrl+R, Ctrl+W and so on. A few keys differ, notably Ctrl+U. On some Mac terminals you must enable Use Option as Meta key for the Alt shortcuts.
What is the difference between Ctrl+U in bash and zsh? In bash, Ctrl+U cuts from the cursor to the start of the line. In zsh's default configuration it cuts the entire line regardless of cursor position. Ctrl+K, cut to end of line, behaves the same in both shells.
How is Ctrl+W different from Alt+Backspace? Ctrl+W deletes back to the previous whitespace, so it removes a whole path in one press. Alt+Backspace also stops at punctuation like slashes and dots, so it removes a single path segment. Use Ctrl+W for words, Alt+Backspace for parts of a path.
What does !$ mean? It expands to the last argument of the previous command. After mkdir -p logs/2026, typing cd !$ becomes cd logs/2026. The Alt+. key does the same thing interactively and lets you cycle through earlier commands' last arguments.
Is the terminal's cut and paste the same as the system clipboard? No. Ctrl+U, Ctrl+K and Ctrl+W store text in the shell's own kill ring, and Ctrl+Y pastes from it. This is independent of the OS clipboard, so you can stash a command line with Ctrl+U and restore it with Ctrl+Y without disturbing what you copied elsewhere.