Introduction
Have you ever needed to re-run a complex command you typed earlier, but couldn't remember it exactly? Or wanted to find that one command from yesterday that solved a specific problem? That's where command history comes in.
Linux bash shell keeps a record of every command you type, allowing you to recall, search, edit, and reuse them. This is one of the most powerful productivity features in the terminal. Instead of retyping long commands or complex pipelines, you can simply recall them from history with a few keystrokes.
In this comprehensive guide, you'll learn everything about bash command history. By the end, you'll be able to navigate your command history efficiently, use powerful search features, execute previous commands with shortcuts, and configure history to suit your workflow.
What is Command History?
Command history is bash's built-in feature that remembers the commands you type. Every time you execute a command, bash:
- Stores it in memory
- Adds it to a history file when you log out (or explicitly save it)
- Makes it available for recall and reuse
This history persists across sessions, so commands from weeks or months ago can still be accessed.
The .bash_history File
Bash stores your command history in a file called .bash_history in your home directory.
Location: ~/.bash_history
View it:
ls -l ~/.bash_history
-rw-------. 1 centos9 centos9 24109 Dec 11 16:30 .bash_history
Notice the permissions: rw------- (600) - only you can read and write it. This is important for security since your history might contain sensitive information.
View the contents:
cat ~/.bash_history | head -10
ls
cd /etc
grep root /etc/passwd
sudo systemctl status sshd
ps aux | grep httpd
df -h
free -m
top
history
exit
When Is History Written to the File?
By default, bash writes command history to .bash_history when you:
- Log out normally (exit the shell)
- Explicitly save it with
history -w
Important: Commands from your current session are stored in memory and won't appear in .bash_history until you log out or manually save them.
The history Command
The history command displays your command history with line numbers.
Basic usage:
history
1 ls
2 cd /etc
3 grep root /etc/passwd
4 sudo systemctl status sshd
5 ps aux | grep httpd
...
1025 history
Each command has a number that you can use to reference and re-execute it.
Show Last N Commands
Show only the last 10 commands:
history | tail -10
1016 cat .bash_history | wc -l
1017 last | tail
1018 history -w
1019 ls -l .bash_history
1020 history | tail
1021 history -d 1025
1022 history | tail
1023 ls -l .bash_history
1024 cat .bash_history | wc -l
1025 history | tail
Or use history's built-in option:
history 10
Search History
Find all commands containing a specific word:
history | grep ssh
42 systemctl status sshd
87 ps aux | grep ssh
234 ssh user@192.168.1.100
456 sudo systemctl restart sshd
1001 ps aux | tee processes.txt | grep ssh
Understanding HISTSIZE and HISTFILESIZE
Two important environment variables control history behavior:
HISTSIZE
HISTSIZE controls how many commands are kept in memory during your current session.
Check it:
echo $HISTSIZE
1000
Default: Usually 1000 commands
What it means: Bash will remember up to 1000 commands in your current session. When you exceed this limit, the oldest commands are removed from memory.
HISTFILESIZE
HISTFILESIZE controls how many commands are stored in the .bash_history file.
Check it:
echo $HISTFILESIZE
1000
Default: Usually 1000 commands
What it means: The .bash_history file will store up to 1000 commands. When this limit is reached, the oldest commands are removed from the file.
Check Current History Count
cat ~/.bash_history | wc -l
1000
If you see exactly 1000, you've hit the limit. Older commands have been deleted.
Why the Default is 1000
The default of 1000 commands is a balance between:
- Usefulness: Enough history to recall recent commands
- Disk space: Doesn't consume too much space
- Security: Limits exposure if history contains sensitive data
- Performance: Keeps history searches fast
For most users, 1000 is sufficient. System administrators often increase it to 10,000 or more.
Configuring History Size
You can customize both HISTSIZE and HISTFILESIZE in your ~/.bashrc file.
Increase History Size
Edit ~/.bashrc:
nano ~/.bashrc
Add or modify these lines:
# Increase command history
HISTSIZE=10000
HISTFILESIZE=10000
Save and apply:
source ~/.bashrc
Verify:
echo $HISTSIZE
10000
echo $HISTFILESIZE
10000
Make History Unlimited
For unlimited history (use with caution):
HISTSIZE=-1
HISTFILESIZE=-1
This will never delete old commands, but your history file will grow indefinitely.
history Command Options
The history command has several useful options.
history -c: Clear History
Clear all history from the current session (in memory):
history -c
After this, history shows nothing:
history
1 history
Note: This only clears memory. It doesn't delete .bash_history until you log out.
history -w: Write History to File
Immediately save current session history to .bash_history:
history -w
Use case: Save important commands before logging out or before clearing history.
Example:
# Check file size before
ls -l ~/.bash_history
-rw-------. 1 centos9 centos9 24109 Dec 11 16:30 .bash_history
# Write current history
history -w
# Check file size after (it updated)
ls -l ~/.bash_history
-rw-------. 1 centos9 centos9 27196 Dec 11 16:35 .bash_history
history -d: Delete Specific Entry
Delete a specific command from history by its number:
history | tail -5
1021 ls
1022 cd /etc
1023 cat /etc/passwd
1024 rm sensitive_file.txt
1025 history | tail -5
# Delete command 1024
history -d 1024
# Verify it's gone
history | tail -5
1021 ls
1022 cd /etc
1023 cat /etc/passwd
1024 history | tail -5
1025 history | tail -5
Use case: Remove sensitive commands (passwords, API keys, etc.) from history.
history -a: Append New Commands to File
Append commands from current session to .bash_history without overwriting:
history -a
This is useful when running multiple bash sessions simultaneously.
history -r: Read History from File
Read .bash_history into current session's memory:
history -r
Use this to reload history after making manual changes to .bash_history.
Executing Commands from History
Instead of retyping commands, you can execute them directly from history using several shortcuts.
Using !! - Repeat Last Command
!! repeats the last command you ran.
Example:
apt update
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
# Oops, forgot sudo. Use !! to repeat:
sudo !!
sudo apt update
[sudo] password for user:
...
What happened: !! was replaced with apt update, so the full command became sudo apt update.
Using !n - Execute Command by Number
Execute a command by its history number:
Example:
history | grep ssh
234 ssh user@192.168.1.100
456 sudo systemctl restart sshd
789 ps aux | grep ssh
# Execute command 234
!234
ssh user@192.168.1.100
Using !string - Execute Last Command Starting with String
Execute the most recent command that starts with a specific string:
Example:
history | tail -5
1020 ls -la /var/log
1021 cat /etc/hosts
1022 grep root /etc/passwd
1023 systemctl status sshd
1024 history | tail -5
# Execute last command starting with "ls"
!ls
ls -la /var/log
drwxr-xr-x. 12 root root 4096 Dec 11 16:40 .
drwxr-xr-x. 20 root root 278 Nov 3 13:53 ..
...
Another example:
!sys
systemctl status sshd
● sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled)
Active: active (running)
Using !?string - Execute Last Command Containing String
Execute the most recent command that contains a specific string (anywhere in the command):
Example:
history | tail -5
1020 ls -la /var/log
1021 cat /etc/hosts
1022 grep root /etc/passwd
1023 ps aux | grep httpd
1024 history | tail -5
# Execute last command containing "httpd"
!?httpd
ps aux | grep httpd
Using !$ - Last Argument of Previous Command
!$ represents the last argument from the previous command.
Example:
cat /etc/ssh/sshd_config
...
(long output)
# Open the same file in an editor:
vim !$
vim /etc/ssh/sshd_config
Another practical example:
mkdir /tmp/my_new_directory
cd !$
cd /tmp/my_new_directory
This saves you from retyping long paths or filenames.
Using !* - All Arguments of Previous Command
!* represents all arguments from the previous command.
Example:
ls -la /etc /var /usr
# Copy all those directories:
cp -r !* /backup/
cp -r /etc /var /usr /backup/
Using Ctrl-R: Reverse Search
The most powerful history feature is reverse search with Ctrl-R.
How Reverse Search Works
- Press
Ctrl-R - Start typing part of a command
- Bash searches backward through history
- Press
Enterto execute, orCtrl-Ragain to find the next match
Example:
Press Ctrl-R:
(reverse-i-search)`':
Type "ssh":
(reverse-i-search)`ssh': ssh user@192.168.1.100
Bash found the most recent command containing "ssh".
- Press Enter: Execute it
- Press Ctrl-R again: Find previous match
- Press Ctrl-G or Esc: Cancel search
- Left/Right arrow: Edit the command before executing
Practical Reverse Search Examples
Example 1: Find a complex pipeline:
# Press Ctrl-R and type "grep"
(reverse-i-search)`grep': ps aux | grep httpd | grep -v grep | awk '{print $2}'
Example 2: Find a command with specific arguments:
# Press Ctrl-R and type "ssh 192"
(reverse-i-search)`ssh 192': ssh -i ~/.ssh/mykey.pem user@192.168.1.50
Example 3: Navigate through multiple matches:
# Press Ctrl-R, type "systemctl"
(reverse-i-search)`systemctl': systemctl restart nginx
# Press Ctrl-R again for previous match
(reverse-i-search)`systemctl': systemctl status sshd
# Press Ctrl-R again
(reverse-i-search)`systemctl': systemctl enable httpd
Navigating History with Arrow Keys
The simplest way to navigate history:
Up Arrow (↑)
- Shows the previous command
- Press multiple times to go further back
Down Arrow (↓)
- Shows the next command (toward more recent)
- Returns to current prompt when you reach the end
Example:
# Current prompt
[user@host ~]$
# Press ↑ once
[user@host ~]$ history | tail
# Press ↑ again
[user@host ~]$ ls -la /var/log
# Press ↑ again
[user@host ~]$ systemctl status sshd
# Press ↓ to go forward
[user@host ~]$ ls -la /var/log
# Press ↓ again
[user@host ~]$ history | tail
# Press ↓ again (back to prompt)
[user@host ~]$
Additional History Features
HISTCONTROL: Control What Gets Saved
The HISTCONTROL variable controls which commands are saved to history.
Check current setting:
echo $HISTCONTROL
ignoredups:ignorespace
Common values:
| Value | Effect |
|-------|--------|
| ignoredups | Don't save duplicate consecutive commands |
| ignorespace | Don't save commands starting with a space |
| ignoreboth | Combine ignoredups and ignorespace |
| erasedups | Remove all previous matching commands from history |
Prevent Commands from Being Saved
Method 1: Start command with a space (if ignorespace is set):
echo $HISTCONTROL
ignoreboth
# This won't be saved (note the leading space):
mysql -u root -p MySecretPassword
Method 2: Clear history after running sensitive command:
mysql -u root -p MySecretPassword
history -d $(history | tail -1 | awk '{print $1}')
Set HISTCONTROL in .bashrc
# In ~/.bashrc
export HISTCONTROL=ignoreboth:erasedups
HISTIGNORE: Ignore Specific Commands
Tell bash to never save certain commands:
# In ~/.bashrc
export HISTIGNORE="ls:pwd:exit:clear:history"
Now ls, pwd, exit, clear, and history won't be saved.
Real-World History Use Cases
Use Case 1: Rerun Complex Commands
You ran a complex pipeline an hour ago:
find /var/log -type f -name "*.log" -mtime +30 -exec gzip {} \;
To run it again:
# Method 1: Search
Ctrl-R, type "find /var"
# Method 2: History grep
history | grep "find /var"
543 find /var/log -type f -name "*.log" -mtime +30 -exec gzip {} \;
!543
Use Case 2: Build on Previous Commands
ls /etc/ssh/
sshd_config ssh_config ...
cat !$/sshd_config
cat /etc/ssh/sshd_config
vim !$
vim /etc/ssh/sshd_config
Use Case 3: Fix Typos Quickly
systenctl status sshd
bash: systenctl: command not found...
# Use !! with string replacement
^systenctl^systemctl
systemctl status sshd
The ^old^new syntax replaces old with new in the previous command.
Use Case 4: Document Your Work
# After solving a problem, review what you did:
history | tail -20 > solution_steps.txt
Use Case 5: Audit Activity
Check what commands were run:
# By current user
cat ~/.bash_history
# System-wide (if you have access)
for user in /home/*; do
echo "=== $user ==="
sudo cat $user/.bash_history | tail -10
done
Best Practices for Command History
1. Increase History Size
For system administrators:
# In ~/.bashrc
HISTSIZE=10000
HISTFILESIZE=10000
2. Add Timestamps to History
See when commands were run:
# In ~/.bashrc
export HISTTIMEFORMAT="%F %T "
Now history shows timestamps:
history | tail -3
1023 2025-12-11 16:45:32 ls -la
1024 2025-12-11 16:46:15 systemctl status sshd
1025 2025-12-11 16:47:03 history | tail -3
3. Sync History Across Multiple Sessions
If you use multiple terminals:
# In ~/.bashrc
shopt -s histappend
export PROMPT_COMMAND="history -a; history -r"
This appends and reads history after each command.
4. Don't Store Sensitive Commands
Use a leading space or delete them:
# mysql -u root -pMyPassword # Leading space - won't be saved
# OR
mysql -u root -pMyPassword
history -d $(history | tail -1 | awk '{print $1}')
5. Regularly Review and Clean History
# Find and remove sensitive patterns
history | grep -i password
history -d <number>
# Or edit .bash_history directly
vim ~/.bash_history
6. Backup Important History
cp ~/.bash_history ~/.bash_history.backup.$(date +%Y%m%d)
Common Pitfalls and How to Avoid Them
Pitfall 1: History Not Saving
Problem: Commands disappear after logout.
Cause: Shell crashed or history -c was run.
Solution: Use history -w to save explicitly before risky operations.
Pitfall 2: Multiple Sessions Overwriting History
Problem: Only the last session's history is saved.
Cause: Each session overwrites .bash_history on exit.
Solution: Set histappend:
shopt -s histappend
Pitfall 3: Can't Find Recent Command
Problem: Recent commands not showing in history.
Cause: They're in memory, not in .bash_history yet.
Solution: Use history command (shows memory) instead of cat ~/.bash_history.
Pitfall 4: Accidentally Executing Wrong Command
Problem: !sys executed the wrong command.
Solution: Preview first:
# In ~/.bashrc
shopt -s histverify
Now !sys will show the command for you to review before executing.
Pitfall 5: Sensitive Data in History
Problem: Passwords or keys stored in history.
Solution: Use HISTIGNORE or leading spaces, and regularly audit:
history | grep -i "password\|secret\|key"
History Command Cheat Sheet
| Command/Shortcut | Description | Example |
|-----------------|-------------|---------|
| history | Show all history | history |
| history 10 | Show last 10 commands | history 10 |
| history \| grep term | Search history | history \| grep ssh |
| history -c | Clear history (memory only) | history -c |
| history -w | Write history to file | history -w |
| history -d N | Delete entry number N | history -d 1024 |
| history -a | Append new commands to file | history -a |
| history -r | Read history from file | history -r |
| !! | Repeat last command | sudo !! |
| !n | Execute command number n | !234 |
| !string | Execute last command starting with string | !ssh |
| !?string | Execute last command containing string | !?httpd |
| !$ | Last argument of previous command | vim !$ |
| !* | All arguments of previous command | cp -r !* /backup/ |
| ^old^new | Replace old with new in previous command | ^tset^test |
| Ctrl-R | Reverse search history | Press Ctrl-R, type search term |
| Ctrl-R again | Find next match in reverse search | While in reverse search |
| Ctrl-G | Cancel reverse search | While in reverse search |
| ↑ (Up arrow) | Previous command | Press ↑ |
| ↓ (Down arrow) | Next command | Press ↓ |
Environment Variables Cheat Sheet
| Variable | Description | Default |
|----------|-------------|---------|
| HISTSIZE | Commands kept in memory | 1000 |
| HISTFILESIZE | Commands stored in file | 1000 |
| HISTFILE | History file location | ~/.bash_history |
| HISTCONTROL | What to ignore | ignoredups |
| HISTIGNORE | Commands to never save | (none) |
| HISTTIMEFORMAT | Timestamp format | (none) |
Practice Labs
Let's practice working with command history.
Lab 1: View Your History
Task: Display all your command history.
Solution
history
Lab 2: Count Your History
Task: Count how many commands are in your current history.
Solution
history | wc -l
Lab 3: View Last 5 Commands
Task: Show only the last 5 commands from your history.
Solution
history | tail -5
# Or:
history 5
Lab 4: Search for Specific Commands
Task: Find all commands in your history that contain the word "systemctl".
Solution
history | grep systemctl
Lab 5: Check History Settings
Task: Display the current values of HISTSIZE and HISTFILESIZE.
Solution
echo $HISTSIZE
echo $HISTFILESIZE
Lab 6: Check History File Size
Task: Count how many lines are in your .bash_history file.
Solution
wc -l ~/.bash_history
# Or:
cat ~/.bash_history | wc -l
Lab 7: Save History Immediately
Task: Write your current session's history to the .bash_history file.
Solution
history -w
Lab 8: Repeat Last Command
Task: Run any command, then repeat it using !!.
Solution
ls -la
!!
Lab 9: Use Last Argument
Task: Create a file, then immediately view it using !$.
Solution
touch /tmp/test_file.txt
cat !$
The !$ expands to /tmp/test_file.txt.
Lab 10: Execute Command by Number
Task: Use history to find a command number, then execute that command using !n.
Solution
history | tail -10
1015 ls -la
1016 cd /tmp
1017 pwd
...
# Execute command 1015
!1015
ls -la
Lab 11: Execute Last Command Starting with String
Task: Execute the most recent command that starts with "ls".
Solution
!ls
Lab 12: Delete a History Entry
Task: View your history, pick a command number, and delete it.
Solution
history | tail -10
1020 ls
1021 pwd
1022 whoami
...
# Delete command 1021
history -d 1021
# Verify it's gone
history | tail -10
Lab 13: Practice Reverse Search
Task: Use Ctrl-R to search for a previous command containing "grep".
Solution
- Press
Ctrl-R - Type "grep"
- Bash shows:
(reverse-i-search)grep': history | grep systemctl` - Press Enter to execute, or Ctrl-R again for next match
Lab 14: Use Arrow Keys
Task: Use the up arrow to navigate to a previous command, edit it, and run it.
Solution
- Press ↑ (up arrow) one or more times
- Use left/right arrows to position cursor
- Edit the command
- Press Enter to execute
Lab 15: Increase History Size
Task: Temporarily set HISTSIZE to 5000 for your current session.
Solution
export HISTSIZE=5000
# Verify
echo $HISTSIZE
5000
Note: This is temporary. To make it permanent, add to ~/.bashrc.
Lab 16: Add Timestamps to History
Task: Enable timestamps for history in your current session.
Solution
export HISTTIMEFORMAT="%F %T "
# Verify
history | tail -3
1023 2025-12-11 17:15:42 ls -la
1024 2025-12-11 17:16:05 pwd
1025 2025-12-11 17:16:20 history | tail -3
Lab 17: Clear History
Task: Clear all command history from your current session (be careful!).
Solution
history -c
# Verify
history
1 history
Note: This only clears memory. The .bash_history file is unchanged until logout.
Lab 18: Backup Your History
Task: Create a backup copy of your .bash_history file with today's date.
Solution
cp ~/.bash_history ~/.bash_history.backup.$(date +%Y%m%d)
# Verify
ls -l ~/.bash_history*
Lab 19: Find Commands from Today
Task: If you have HISTTIMEFORMAT enabled, find all commands you ran today.
Solution
# First enable timestamps if not already:
export HISTTIMEFORMAT="%F %T "
# Then search for today's date
history | grep "$(date +%F)"
Lab 20: Prevent Command from Being Saved
Task: Run a command with a leading space so it won't be saved to history (requires HISTCONTROL=ignorespace or ignoreboth).
Solution
# Check if ignorespace is set
echo $HISTCONTROL
ignoreboth
# Run command with leading space (note the space before echo):
echo "This won't be in history"
# Verify it's not in history
history | tail -5
# (The echo command should not appear)
Key Takeaways
-
Command History Saves Commands: Bash remembers every command you type
-
Storage Locations:
- Memory: Current session (controlled by
HISTSIZE) - File:
~/.bash_history(controlled byHISTFILESIZE)
- Memory: Current session (controlled by
-
Default Limit: 1000 commands (can be increased)
-
The history Command:
history- show all historyhistory -c- clear history (memory)history -w- write to file immediatelyhistory -d N- delete entry number N
-
Execution Shortcuts:
!!- repeat last command!n- execute command number n!string- execute last command starting with string!$- last argument of previous command
-
Reverse Search:
Ctrl-Ris the most powerful search feature -
Arrow Keys: Use ↑ and ↓ to navigate history
-
Configuration: Customize in
~/.bashrc:- Increase
HISTSIZEandHISTFILESIZE - Add
HISTTIMEFORMATfor timestamps - Set
HISTCONTROLto control what's saved
- Increase
-
Security: Be careful with sensitive data in history
-
Productivity: Mastering history saves enormous time and effort
What's Next?
You now understand how to leverage bash command history for maximum productivity. In the next post, Part 49: Command Line Completion and bash-completion, we'll learn how to:
- Use Tab completion for commands, files, and directories
- Understand single vs double Tab press
- Install and configure bash-completion package
- Get intelligent completion for specific commands
- Create custom completion scripts
- Speed up your command-line workflow even more
Tab completion is another essential productivity feature that, combined with command history, makes you incredibly efficient in the terminal. See you in the next post!

