Linux terminal shortcuts come from three different places, and that is why a key that works on one machine does nothing on the next. Line editing such as Ctrl+A, Ctrl+W and Alt+. belongs to GNU Readline inside Bash (or to ZLE inside zsh). Ctrl+C, Ctrl+Z and Ctrl+S belong to the kernel’s terminal driver and show up in stty -a. Copy, paste and new tabs belong to your terminal app, which sees the key before the shell does.
This cheat sheet covers all three layers for Bash and zsh, with a one-page PDF you can print. Keys went through a raw pseudo-terminal, not tmux. The retest turned up two things older cheat sheets get wrong: Ctrl+X Ctrl+E fails on a stock Rocky Linux install, and Ctrl+X Ctrl+R won’t load a brand-new ~/.inputrc. Every shell shortcut below was pressed for real in Bash and zsh on Ubuntu 26.04 and Rocky Linux 10 in October 2026, and the terminal app keys were read from the installed defaults on both.
Linux Terminal Shortcuts Cheat Sheet (Quick Reference)
These tables are the whole cheat sheet, and the PDF is built from them. Alt means the Alt key in most terminal apps; if one doesn’t pass Alt through, press Esc and then the letter. Every shell key in them behaved as written in Bash on both distros, the history-expansion forms were run with !echo in place of !ssh, and the zsh exceptions are flagged in the zsh section further down.
Move the cursor
| Shortcut | What it does |
|---|---|
Ctrl+A | Jump to the start of the line |
Ctrl+E | Jump to the end of the line |
Ctrl+F / Ctrl+B | Forward / back one character |
Alt+F / Alt+B | Forward / back one word |
Ctrl+X Ctrl+X | Swap the cursor with the mark (start of a fresh line) |
Cut, paste and undo
| Shortcut | What it does |
|---|---|
Ctrl+U | Cut from the cursor back to the line start (zsh: whole line) |
Ctrl+K | Cut from the cursor to the line end |
Ctrl+W | Cut the word before the cursor, up to a space (Bash) |
Alt+Backspace | Cut the word before the cursor, stopping at / (Bash) |
Alt+D | Cut the word after the cursor |
Ctrl+Y | Paste the last cut text |
Alt+Y | Right after Ctrl+Y, cycle to an older cut |
Ctrl+_ | Undo the last edit (also Ctrl+X Ctrl+U) |
Alt+R | Undo every change to the line (Bash only) |
Fix typos and case
| Shortcut | What it does |
|---|---|
Ctrl+D | Delete the character under the cursor (empty line: exit) |
Ctrl+H | Delete the character before the cursor |
Ctrl+T | Swap the two characters around the cursor |
Alt+T | Swap the last two words |
Alt+U | Uppercase to the end of the word |
Alt+L | Lowercase to the end of the word |
Alt+C | Capitalise the word |
Ctrl+V | Insert the next key literally (a real Tab, say) |
Search and reuse history
| Shortcut | What it does |
|---|---|
Ctrl+R | Search history backwards as you type |
Ctrl+S | Search forwards (after stty -ixon) |
Ctrl+G | Cancel the search, restore the line |
Ctrl+P / Ctrl+N | Previous / next command |
Alt+. | Insert the last argument of the previous command (repeat for older) |
Ctrl+O | Run this history line and load the next one |
Alt+# | Comment the line out and save it to history (Bash only) |
Ctrl+L | Clear the screen, keep the line you are typing |
History expansion
| Type | Expands to |
|---|---|
!! | The whole previous command (sudo !! reruns it as root) |
!$ | Last argument of the previous command |
!* | All arguments of the previous command |
!ssh | Most recent command starting with ssh |
!ssh:p | Print that command without running it |
^old^new | Rerun the previous command with old replaced |
Stop, suspend and resume
| Shortcut | What it does |
|---|---|
Ctrl+C | Interrupt the running program (SIGINT, exit 130) |
Ctrl+\ | Quit it with a core dump (SIGQUIT, exit 131) |
Ctrl+Z | Suspend it (SIGTSTP); resume with fg or bg |
jobs | List suspended and background jobs |
kill %1 | Terminate job 1 |
Ctrl+S / Ctrl+Q | Freeze / resume screen output (XOFF / XON) |
Complete and edit long commands
| Shortcut | What it does |
|---|---|
Tab | Complete a command, file name or path |
Tab Tab | List every match when there is more than one |
Alt+? | List matches without changing the line (zsh: which-command) |
Alt+* | Insert every match into the line (Bash only) |
Ctrl+X Ctrl+E | Edit the line in $EDITOR, run it when the editor exits (Bash only) |
Ctrl+X Ctrl+R | Re-read the inputrc the shell started with |
Terminal app keys (Ptyxis defaults)
| Shortcut | What it does |
|---|---|
Ctrl+Shift+C | Copy the selection |
Ctrl+Shift+V | Paste |
Ctrl+Shift+T | New tab |
Ctrl+Shift+N | New window |
Ctrl+Shift+W | Close the tab |
Ctrl+Shift+F | Search the scrollback |
Ctrl+PgUp / Ctrl+PgDn | Previous / next tab |
Alt+1 to Alt+0 | Jump to tab 1 to 10 |
Ctrl+plus / Ctrl+minus | Zoom in / out (Ctrl+0 resets) |
F11 | Toggle full screen |
If you only learn five from all of that, make them Ctrl+R, Ctrl+A, Ctrl+E, Ctrl+W and Alt+. because they save the most typing on a normal day. The sections below show what each group did in the lab, including the cases where a shortcut does something other than what most cheat sheets claim.
Check which layer owns a key
Two commands tell you who handles a key on your own machine, and they’re worth running before you rebind anything. stty -a prints the control characters the terminal driver grabs before the shell sees them. bind -p prints every Readline binding Bash has loaded. Start with the driver, because it wins:
stty -a | tr ";" "\n" | sed "s/^ *//" | grep -E "^(intr|quit|erase|kill|eof|start|stop|susp|rprnt|werase|lnext|discard) "
Plain stty -a prints one long block, so the filter splits it and keeps only the control characters. Ubuntu 26.04 and Rocky Linux 10 printed the same twelve lines:
intr = ^C
quit = ^\
erase = ^?
kill = ^U
eof = ^D
start = ^Q
stop = ^S
susp = ^Z
rprnt = ^R
werase = ^W
lnext = ^V
discard = ^O
Ctrl+C, Ctrl+\, Ctrl+Z, Ctrl+S and Ctrl+Q act at the driver level, so they reach whatever program holds the foreground, not only the shell. Ctrl+U, Ctrl+W and Ctrl+R are listed too, but at a Bash prompt Readline switches the driver’s line editing off and takes those keys over, which is why Ctrl+R searches history instead of reprinting the line. Next, ask Readline what a key does. bind -P prints the function first and every key bound to it:
bind -P | grep -E "^(beginning-of-line|reverse-search-history|unix-word-rubout|yank-last-arg|edit-and-execute-command) "
\C- is Ctrl and \e is Alt or Esc. The output was identical on both distros. Of the Home key codes on the first line, \e[1~ comes from /etc/inputrc and the other two are Readline’s built-in defaults:
beginning-of-line can be found on "\C-a", "\eOH", "\e[1~", "\e[H".
edit-and-execute-command can be found on "\C-x\C-e".
reverse-search-history can be found on "\C-r".
unix-word-rubout can be found on "\C-w".
yank-last-arg can be found on "\e.", "\e_".
We grepped bind -p for every key in the quick-reference tables on both systems, and all of them were bound to the same function on Ubuntu and Rocky. When a key misbehaves, the two lists tell you where to look:
- Listed in
stty -a: the terminal driver, changed withstty - Listed in
bind -p: Readline, changed in~/.inputrc - In neither: your terminal app or tmux caught it first
Readline treats Alt as an Esc prefix, which is the \e in those bindings. If an Alt shortcut does nothing in your terminal app, press Esc and then the letter. Esc then U on echo hello gave echo HELLO, the same as Alt+U.
Edit the line without the arrow keys
Readline’s cut commands don’t throw text away. They push it onto a kill ring, and Ctrl+Y pastes it back, so Ctrl+U is a safe way to park a half-typed command while you check something else. Typing echo cut-me, pressing Ctrl+U, typing echo pasted: and pressing Ctrl+Y left echo pasted: echo cut-me on the line. The ring holds more than one entry: after cutting one and then two with Ctrl+W, Ctrl+Y pasted two, and Alt+Y straight after swapped it for one.
Ctrl+W and Alt+Backspace look alike but stop in different places, and on paths the difference matters. Ctrl+W stops only at spaces, so on echo /var/log/nginx/ it ate the whole path in one go. Alt+Backspace in Bash treats the slash as a word break, and the same line came out as echo /var/log/. Use Alt+Backspace when you only want to drop the last directory and Ctrl+W when you want the whole argument gone.
The case and swap keys are quicker to trust once you’ve seen them work. With the cursor at the end of echo second first, Alt+T produced echo first second. Alt+B then Alt+U turned echo hello into echo HELLO, and Alt+C gave echo Hello. Ctrl+T on echo ab gave echo ba. Ctrl+_ right after a Ctrl+W put undo-me straight back, and Alt+R on a freshly typed line cleared it, because “every change” includes the typing.
Ctrl+X Ctrl+X is usually described as “toggle to the start of the line”, which is only true on a fresh line. It swaps the cursor with the mark, and on a line you have just typed the mark sits at the start. We typed echo abcdef, pressed Ctrl+X Ctrl+X, typed X, pressed it again and typed Y. Bash left Xecho abcdeYf: the mark stayed at character 11, which the inserted X had pushed one short of the end, so the second press did not land at the end of the line. zsh moves the mark along with inserted text and left Xecho abcdefY.
Search history with Ctrl+R and Alt+.
Ctrl+R pays you back fastest. Press it, type any part of an old command, and Readline shows the newest match. Press Ctrl+R again to step to an older match, Enter to run it, or Right arrow to leave the search with the match on the line and the cursor where the match was found, ready to edit. Typing uniq after Ctrl+R showed this on both distros:
(reverse-i-search)`uniq': echo uniquemarker123
Ctrl+G leaves the search and restores whatever line you had before. Alt+. is the shortcut most people learn late and then use all day: after mkdir -p /tmp/demo-dir, typing cd and pressing Alt+. completed the line to cd /tmp/demo-dir. Pressing it twice walks back one more command, so after echo aaa and echo bbb, two presses inserted aaa.
Ctrl+O replays a block of commands, which beats arrowing back once per line when you rerun a set of steps after a fix. This is the sequence we ran:
- Run
echo a,echo bandecho c - Press Ctrl+P until
echo ais on the line - Press Ctrl+O: it runs
echo aand loadsecho b - Press Ctrl+O again for each remaining line
Alt+# is for the long command you are not ready to run. It prefixes the line with #, saves it to history and does nothing else, so echo IFS=$IFS came back on the next Ctrl+P as #echo IFS=$IFS.
Use history expansion with !
History expansion is not a key binding. The shell rewrites the line when you press Enter, then prints the expanded command before running it, so you always see what actually ran. Quick substitution is the form that fixes typos. After echo teh cat, we typed the caret form:
^teh^the
Both shells echoed the rewritten command and then ran it:
echo the cat
the cat
The other forms behaved the same way. After ls /etc/hostname, typing cat !$ ran cat /etc/hostname. After echo a b c, printf '%s\n' !* printed the three arguments on separate lines. On Rocky, id -un followed by sudo !! printed sudo id -un and then root.
Be careful with !! and !ssh on a root shell, because they run the moment you press Enter. When you’re not sure what a pattern will match, add :p first. !echo:p printed echo uniquemarker123 again without running it, and the printed line went into history, so Up brought it back ready to edit.
Stop, suspend and resume programs
These keys come from the terminal driver, so they work the same under Bash and zsh once a program is in the foreground. Ctrl+C on sleep 300 left $? at 130 (128 plus SIGINT’s 2) on both distros. Ctrl+\ sends SIGQUIT, which also asks for a core dump: Bash printed Quit (core dumped), zsh printed zsh: quit (core dumped), and $? was 131 in both. Keep Ctrl+\ for a program that ignores Ctrl+C, not as a faster Ctrl+C, because every press leaves a core dump for the system to process.
Ctrl+Z doesn’t end anything. It parks the job, which keeps holding its files and ports until you resume or kill it. We ran this round trip in Bash on Ubuntu 26.04:
- Run
sleep 300and press Ctrl+Z - Run
jobs, thenbg, thenjobsagain - Run
kill %1, then any command so Bash reports the job
These are the lines Bash printed across those steps, with the prompts left out:
^Z
[1]+ Stopped sleep 300
[1]+ Stopped sleep 300
[1]+ sleep 300 &
[1]+ Running sleep 300 &
[1]+ Terminated sleep 300
fg instead of bg brings the job back to the foreground, where Ctrl+C can end it. zsh reports the same states in its own words: zsh: suspended sleep 300 after Ctrl+Z, then continued, running and terminated.
Ctrl+D does two jobs depending on the line. With text on it, it deletes the character under the cursor: at the start of echo abc it left cho abc. On an empty line it sends end-of-file and the shell exits, which we confirmed by watching $SHLVL drop by one after Ctrl+D in a nested shell. IGNOREEOF was unset on both distros. If Ctrl+D has logged you out of a server once too often, add export IGNOREEOF=1 to ~/.bashrc. With it set, the first Ctrl+D printed Use "exit" to leave the shell. and the second one exited. In zsh the equivalent is setopt ignore_eof, which answered with zsh: use 'exit' to exit.
Ctrl+S is the key that makes people think their terminal froze, because it did. It sends XOFF and the terminal stops showing output until Ctrl+Q sends XON. We started a loop printing one line a second and pressed Ctrl+S about two seconds in. 3.5 seconds later the screen still ended on the line that was showing at the keypress (line2 on Rocky, line3 on Ubuntu), and Ctrl+Q let the rest through to line5. ixon was on by default on both distros. If you never use flow control, turn it off so Ctrl+S reaches the shell as forward history search, the partner to Ctrl+R:
stty -ixon
After that, Ctrl+S opened (i-search) in Bash and fwd-i-search: in zsh instead of freezing the screen. The setting lasts for the current terminal only. To keep it, add this line to ~/.bashrc (or ~/.zshrc); the test stops stty from complaining when a non-interactive script sources the file:
[[ $- == *i* ]] && stty -ixon
Open a new terminal afterwards and Ctrl+S searches instead of freezing.
Fix Ctrl+X Ctrl+E on Rocky Linux
Ctrl+X Ctrl+E opens the current line in a text editor and runs it when the editor exits, which is the cleanest way to fix a long for loop or a docker run with ten flags. Which editor opens depends on the distro, and on a stock Rocky Linux 10 box the answer is none. EDITOR and VISUAL were both empty on the two systems, and Bash only falls back when they are:
- Ubuntu 26.04: opened
/usr/bin/editor /tmp/bash-fc.*, which the alternatives system points at nano - Rocky Linux 10: tried upstream Bash’s fallback, emacs, which is not installed
- zsh on either: nothing, because Ctrl+X Ctrl+E is not bound
The Rocky case looks like this. The bind -P output proves the key is bound, the empty variables explain the fallback, and the last line is what pressing Ctrl+X Ctrl+E on echo from-editor produced:

Name an editor that exists and the key works. Rocky’s minimal install ships vi and no nano, so add export EDITOR=vi to ~/.bashrc (or install nano and point at that). With EDITOR=vi exported, the same key opened the line in vi as a /tmp/bash-fc.* file on both distros. VISUAL wins over EDITOR if both are set, so check both when the wrong editor appears. One behaviour to know before you rely on it: the fc builtin behind this key runs whatever is in the temporary file when the editor exits successfully (the check is in Bash’s fc source; the manual only says the edited commands are executed), so quitting without saving still runs the original line. To cancel, delete the buffer’s contents or quit with an error (:cq in vi).
Set your own bindings in ~/.inputrc
Readline settings and custom bindings go in ~/.inputrc, and they apply to every program that uses Readline, not only Bash. Get one thing right first: when ~/.inputrc exists, Readline reads it instead of /etc/inputrc. Both distros put the Home and End key codes in the system file, and a test shell with a one-line ~/.inputrc had zero bindings for \e[1~ and \e[4~. Start the file with an include so you keep them. Open it in vi, which both distros ship (Rocky’s minimal install has no vim or nano):
vi ~/.inputrc
This is the file we tested. The two settings make completion ignore case and list every match on the first Tab:
$include /etc/inputrc
set completion-ignore-case on
set show-all-if-ambiguous on
Don’t reach for Ctrl+X Ctrl+R yet. It re-reads the init file the shell loaded at startup, and a shell started before ~/.inputrc existed loaded /etc/inputrc. Pressing Ctrl+X Ctrl+R in that shell changed nothing on either distro. Load the new file into the running shell by name:
bind -f ~/.inputrc
New shells read the file on their own, and from then on Ctrl+X Ctrl+R picks up edits to it: a line appended to the file in a shell that started with it was live after one press. Confirm what’s active:
bind -v | grep -E "completion-ignore-case|show-all-if-ambiguous"
Both variables should read on; they read off before the file was loaded:
set completion-ignore-case on
set show-all-if-ambiguous on
With the file loaded, a single Tab on ls /etc/HOS listed the host* files and rewrote the word to lowercase host; without it, the same Tab did nothing. Rocky listed three files and Ubuntu five, because Rocky 10 ships no hosts.allow or hosts.deny. The full list of settings is in the Readline init file section of the Bash manual, and our guide to customising Bash with bash-it layers prompts and aliases on top.
Adjust Linux terminal shortcuts for zsh
zsh does not use Readline. Its line editor, ZLE, copies most of the emacs-style keys, so the quick-reference tables mostly hold, but a few keys stop in different places or aren’t bound at all. We pressed the same key sequences in zsh with no config (zsh -f) and in stock zsh with an empty ~/.zshrc, which reads the distro’s system zshrc. Both gave the same results on both distros, and these were the differences from Bash:
| Key | Bash | zsh (emacs keymap) |
|---|---|---|
Ctrl+U | Cuts back to the line start | Cuts the whole line (kill-whole-line) |
Alt+F | Stops at the end of the next word | Stops at the start of the next word |
Alt+Backspace | /var/log/nginx/ becomes /var/log/ | Cuts the whole path, because / is in WORDCHARS |
Alt+? | Lists completions | Runs which-command on the first word |
Alt+* | Inserts all completions | Not bound |
Ctrl+X Ctrl+E | Edits the line in an editor | Not bound |
Alt+R | Reverts the line | Not bound |
Alt+# | Comments the line out | Not bound |
Ctrl+W | Cuts back to the previous space | backward-kill-word, which also stops at characters outside WORDCHARS |
Ctrl+X Ctrl+X | Mark stays put when you type before it | Mark moves with inserted text |
Tab Tab | Lists the matches | Lists them, then the second Tab inserts the first match |
Ctrl+R | (reverse-i-search) | bck-i-search:, same job |
Alt+F is easy to miss until it bites. We typed echo one two, pressed Alt+B and typed X, then Ctrl+A, Alt+F and typed Y. Bash left echoY one Xtwo and zsh left echo Yone Xtwo, so in zsh a word-jump lands on the next word’s first letter. Alt+? is the one that surprises people, because it runs something. On Rocky, Alt+? on a line starting with ls printed ls --color=auto, the alias Rocky’s startup files define, while under zsh -f and on Ubuntu it printed /usr/bin/ls. Ctrl+O, Alt+., Ctrl+Y and Alt+Y, Ctrl+T, Alt+T and the case keys all behaved as they do in Bash.
The keymap itself is the bigger trap. With EDITOR unset, zsh picked the emacs keymap (bindkey -A emacs main). With EDITOR=vim in the environment, the same zsh -f started in vi insert mode (bindkey -A viins main), and Ctrl+A, Ctrl+E and Alt+. stop doing what this page says. Neither distro’s system zshrc forces a keymap (Rocky’s has bindkey -e commented out), so put bindkey -e in ~/.zshrc if you set EDITOR=vim. A framework can rebind keys too, so after following our guide to installing zsh with Oh My Zsh, run bindkey rather than trusting this table. If you are still choosing a shell, the comparison of Linux and macOS shells covers fish, which sits outside both Readline and ZLE.
Know the keys your terminal app takes
The terminal app sees every key before the shell does, so anything it binds never reaches Bash or zsh. That is why copy and paste use Ctrl+Shift+C and Ctrl+Shift+V: plain Ctrl+C has to reach the driver as SIGINT. Ubuntu 26.04’s desktop recommends Ptyxis, and Rocky Linux 10 has no gnome-terminal package in its default repositories, so Ptyxis is the terminal you’ll meet on both. We read its default bindings from the installed GSettings schema on each distro, and the shortcuts in the quick-reference table were identical.
Two of those defaults collide with keys this page relies on, and a third is easy to hit by accident. Ptyxis takes Alt+1 through Alt+0 for tab switching, which hides Readline’s digit-argument (\e1 and friends, still bound in bind -p). It takes F10 for its menu, which matters in programs such as htop and Midnight Commander where F10 means quit. And Ctrl+Shift+A selects the whole scrollback, which is easy to confuse with Ctrl+A when your hand slips. If you live in tmux, its prefix key adds a fourth layer above all of this; our tmux guide covers those bindings.
For the reasons behind all three layers rather than just the keys, The Linux Command Line, 3rd Edition (paid link) by William Shotts is the book we hand to people new to the shell. It covers Readline editing, history expansion and job control properly, and our list of books to learn Linux explains where it fits against the others. The short version after this retest: learn Ctrl+R, Alt+. and Ctrl+X Ctrl+E first, set EDITOR on every Rocky box you touch, and load a new ~/.inputrc with bind -f instead of trusting Ctrl+X Ctrl+R.