Command History & Shortcuts
When you administer a Linux server, you spend most of your day typing commands into a shell (the program that reads your typed commands and runs them; on Ubuntu the default shell is Bash, short for “Bourne Again SHell”). The difference between a slow engineer and a fast one is rarely talent — it is muscle memory for a handful of small tricks. This page covers command history, the !! shortcut, reverse search with Ctrl+R, tab completion, and the editing keyboard shortcuts every Bash user should know. None of these are hard, and together they save you hours every week.
Command history
Bash remembers the commands you type. That list is your history. Run the history command to see it:
history
Output:
496 cd /etc/nginx/sites-available
497 sudo nano default
498 sudo nginx -t
499 sudo systemctl reload nginx
500 history
Each line has a number you can reuse. The history is kept in memory during your session and written to a file called ~/.bash_history when you log out (the ~ means your home directory, e.g. /home/ubuntu).
To re-run a command by its number, type ! followed by the number:
!498
That re-runs sudo nginx -t. To run the most recent command that started with some text, use ! plus that text:
!sudo
This re-runs the last command beginning with sudo. Be careful — it runs immediately. To preview it first, add :p (print) so Bash shows the command without executing it:
!sudo:p
Searching history with grep
Your history can hold thousands of entries. To find a specific old command, pipe history into grep (a tool that filters lines matching a pattern):
history | grep systemctl
Output:
461 sudo systemctl restart postgresql
499 sudo systemctl reload nginx
503 sudo systemctl status ufw
Repeating the last command with !!
!! (two exclamation marks) means “the entire previous command”. Its most common use is when you forget sudo (the command that runs something as the administrator). Instead of retyping the whole line:
apt update
Output:
Reading package lists... Done
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
Just prefix !! with sudo:
sudo !!
Bash expands !! to apt update, so it runs sudo apt update. You can also reuse just the last argument of the previous command with !$. This is handy when you create a file and then act on it:
sudo nano /etc/nginx/sites-available/myapp
sudo ln -s !$ /etc/nginx/sites-enabled/
Here !$ becomes /etc/nginx/sites-available/myapp.
Gotcha:
!!and!sudorun instantly with no confirmation. Never blindly chain history expansion into destructive commands likermorsudo. When in doubt, add:pto print first, or press the Up arrow to load the command into your prompt so you can read it before hitting Enter.
Reverse search with Ctrl+R
Pressing the Up arrow walks back through history one line at a time, which is slow if the command was 30 entries ago. Ctrl+R (hold Ctrl, press R) opens an interactive reverse search: you type part of a command and Bash finds the most recent match as you type.
- Press
Ctrl+R. The prompt changes to(reverse-i-search). - Start typing, e.g.
nginx. - Bash shows the latest match. Press
Ctrl+Ragain to step to older matches. - Press Enter to run it, or the Right arrow (or
Tab) to edit it first. - Press Ctrl+G to cancel and keep your prompt empty.
(reverse-i-search)`nginx': sudo systemctl reload nginx
Ctrl+R is the single biggest time-saver in this list. Once it is muscle memory, you will rarely retype a long command again.
Tab completion
Press Tab and Bash tries to finish what you are typing — file names, directory names, and command names. Type a few letters and press Tab:
cd /etc/ng
Press Tab and it completes to /etc/nginx/. If more than one option matches, press Tab twice to list them all:
systemctl res
Output:
reset-failed restart resume
On Ubuntu 22.04/24.04, the bash-completion package adds smart completion for many tools — for example systemctl <Tab> lists subcommands and even service names. It is installed by default, but if completion seems limited, install it and reopen your terminal:
sudo apt install bash-completion
When to use it: always. Tab completion is also a safety net — if a path does not complete, you typed it wrong, catching typos before they cause errors.
Keyboard shortcuts
Bash uses Emacs-style key bindings by default for editing the current line. These work whether the line is empty or half-typed.
| Shortcut | What it does | When to use |
|---|---|---|
Ctrl+C | Cancel the current command / kill the running program | Stop a hung command or abandon a half-typed line |
Ctrl+A | Jump to the start of the line | Add sudo before a long command |
Ctrl+E | Jump to the end of the line | Continue editing after fixing the start |
Ctrl+L | Clear the screen (same as clear) | Tidy a cluttered terminal without losing history |
Ctrl+U | Delete from cursor to start of line | Wipe a wrong command and start over |
Ctrl+K | Delete from cursor to end of line | Trim a trailing mistake |
Ctrl+W | Delete the word before the cursor | Fix one wrong argument |
Ctrl+D | Send EOF / log out of the shell | Exit a session or close cat input |
Alt+B / Alt+F | Move back / forward one word | Navigate a long line quickly |
A few notes that trip people up:
Ctrl+Cdoes not copy text in most Linux terminals — it cancels. To copy, useCtrl+Shift+Cand paste withCtrl+Shift+V.Ctrl+Lonly scrolls the old output out of view; it does not erase your history.Ctrl+Don an empty prompt logs you out, which can be a surprise over SSH (Secure Shell, the protocol you use to log into remote servers).
Best Practices
- Reach for
Ctrl+Rbefore the Up arrow — searching beats scrolling for anything more than a few commands back. - Use
sudo !!to re-run the last command with admin rights instead of retyping it. - Add
:pto any history expansion (!!:p,!500:p) when you want to preview before running. - Lean on
Tabconstantly; double-Tabto list options and catch path typos early. - Increase how much history Bash keeps by adding
HISTSIZE=10000andHISTFILESIZE=20000to~/.bashrc, then runsource ~/.bashrc. - Keep secrets out of history: prefix a sensitive command with a space (with the default
HISTCONTROL=ignorespace) so it is never saved.