Introduction
Imagine typing long file paths, complex commands, or remembering exact option names every single time you use the terminal. It would be tedious, error-prone, and incredibly slow. Fortunately, bash provides one of the most powerful productivity features in the Linux terminal: Tab completion.
Tab completion automatically completes what you're typing—whether it's a command name, file path, directory name, or even command-specific arguments. A single press of the Tab key can save you dozens of keystrokes and eliminate typos. It's one of those features that once you master it, you'll wonder how you ever worked without it.
In this comprehensive guide, you'll learn everything about Tab completion and the bash-completion package. By the end, you'll be able to leverage completion for commands, files, variables, and even install advanced completion that understands specific command syntax.
What is Tab Completion?
Tab completion is bash's intelligent auto-completion system. When you press the Tab key while typing a command, file path, or argument, bash attempts to complete what you're typing based on available options.
How it works:
- You start typing something
- Press Tab
- Bash looks at what you've typed
- If there's only one match, bash completes it automatically
- If there are multiple matches, bash either shows options or completes as much as possible
Why it matters:
- Speed: Type less, work faster
- Accuracy: Avoid typos in long filenames or paths
- Discovery: Find available commands and options without documentation
- Productivity: One of the most-used features by experienced Linux users
Basic Tab Completion
Single Tab Press
When you press Tab once, bash tries to complete what you're typing.
Example 1: Complete a command
# Type "sys" and press Tab
sys[Tab]
# Bash completes to:
systemctl
If only one command starts with "sys", bash completes it automatically.
Example 2: Complete a filename
# Type "ls Doc" and press Tab
ls Doc[Tab]
# Bash completes to:
ls Documents/
Example 3: Complete a path
# Type "cd /e" and press Tab
cd /e[Tab]
# Bash completes to:
cd /etc/
Double Tab Press
When you press Tab twice, bash shows you all possible completions if there are multiple matches.
Example: Multiple matches
# Type "user" and press Tab twice
user[Tab][Tab]
useradd userdel usermod users
Bash displays all commands starting with "user".
Another example: See all files
# In a directory with multiple files starting with "test"
ls test[Tab][Tab]
test1.txt test2.txt test_backup.txt testing.log
Partial Completion
If multiple matches share a common prefix, bash completes up to the point where they differ.
Example:
# You have: file1.txt, file2.txt, file_backup.txt
ls f[Tab]
# Bash completes to:
ls file
# Then press Tab twice to see options:
ls file[Tab][Tab]
file1.txt file2.txt file_backup.txt
# Type "1" and Tab again:
ls file1[Tab]
# Completes to:
ls file1.txt
Command Name Completion
Bash can complete command names based on what's in your PATH.
Complete Full Commands
# Type "systemc" and press Tab
systemc[Tab]
systemctl
# Type "ip" and press Tab twice
ip[Tab][Tab]
ip ip6tables ipcalc ipcrm ipcs
Discover Available Commands
Use Tab completion to explore what commands are available:
# See all commands starting with "net"
net[Tab][Tab]
netstat netcat network-manager networkctl
# See all commands starting with "sys"
sys[Tab][Tab]
sysctl systemctl systemd system-config-printer
This is incredibly useful when you can't remember the exact command name.
Case Sensitivity
Tab completion is case-sensitive by default:
# This works:
Desk[Tab]
Desktop/
# This doesn't work (no completion):
desk[Tab]
# (no match if the directory is "Desktop")
File and Directory Completion
Tab completion shines when working with files and directories.
Complete File Names
# List a specific file
ls -l do[Tab]
ls -l document.txt
# Edit a configuration file
vim /etc/ss[Tab]
vim /etc/ssh/
# Press Tab again:
vim /etc/ssh/sshd_[Tab]
vim /etc/ssh/sshd_config
Complete Directory Paths
# Navigate to a directory
cd /v[Tab]
cd /var/
# Continue the path:
cd /var/l[Tab]
cd /var/log/
# Even deeper:
cd /var/log/au[Tab]
cd /var/log/audit/
Work with Long File Names
Tab completion is essential for long or complex filenames:
# Create a file with a very long name
touch very_long_filename_that_would_be_annoying_to_type.txt
# Use it with Tab completion:
cat v[Tab]
cat very_long_filename_that_would_be_annoying_to_type.txt
From the lfcs-rough.txt example:
touch kfnkjsdnfkjsnalfklsfnkjsdnkjfnksjdnfgsnzkjfdgfnkernjkzndskl
# Later, just type:
ls -l kfn[Tab]
ls -l kfnkjsdnfkjsnalfklsfnkjsdnkjfnksjdnfgsnzkjfdgfnkernjkzndskl
You save yourself from typing 60+ characters!
Hidden Files Completion
Tab completion works with hidden files (those starting with .):
# In your home directory
cat .[Tab][Tab]
.bash_history .bash_logout .bash_profile .bashrc
# Complete a specific hidden file:
cat .bash_h[Tab]
cat .bash_history
Variable Name Completion
You can use Tab completion with shell variables when using $.
Complete Variable Names
# Type "echo $HIS" and press Tab twice
echo $HIS[Tab][Tab]
$HISTCMD $HISTCONTROL $HISTFILE $HISTFILESIZE $HISTSIZE
# Complete a specific one:
echo $HISTF[Tab]
echo $HISTFILE
From the lfcs-rough.txt example:
echo $HIST[Tab][Tab]
$HISTCMD $HISTCONTROL $HISTFILE $HISTFILESIZE $HISTSIZE
echo $HISTFILESIZE
1000
Common Variables to Explore
# See all PATH-related variables
echo $PATH[Tab][Tab]
# See all HOME-related variables
echo $HOME[Tab][Tab]
# See all SHELL-related variables
echo $SHELL[Tab][Tab]
Limitations of Basic Tab Completion
Basic Tab completion has some limitations:
1. Command-Specific Arguments Not Completed
Basic bash completion doesn't understand command-specific options:
# This doesn't autocomplete systemctl service names:
systemctl restart [Tab][Tab]
# (shows all files in current directory, not services)
# This doesn't autocomplete Git branches:
git checkout [Tab][Tab]
# (shows files, not branches)
2. No Context-Aware Completion
# ssh completion doesn't know about hosts
ssh user@[Tab]
# (no completion)
# apt doesn't complete package names (without bash-completion)
sudo apt install vim[Tab]
# (no smart completion)
This is where bash-completion package comes in.
Installing bash-completion
The bash-completion package provides intelligent, context-aware completion for hundreds of commands.
Check if Already Installed
# Check if bash-completion is installed
dpkg -l | grep bash-completion # Debian/Ubuntu
rpm -qa | grep bash-completion # RHEL/CentOS
# Or check if the directory exists:
ls /usr/share/bash-completion/
Install on Different Distributions
Ubuntu/Debian:
sudo apt update
sudo apt install bash-completion
CentOS/RHEL/Rocky Linux:
sudo dnf install bash-completion
# Or on older systems:
sudo yum install bash-completion
Fedora:
sudo dnf install bash-completion
Arch Linux:
sudo pacman -S bash-completion
Enable bash-completion
After installation, you may need to enable it:
For system-wide use, it's usually enabled by default. Check /etc/profile.d/bash_completion.sh exists:
ls -l /etc/profile.d/bash_completion.sh
For your user, ensure it's loaded in ~/.bashrc:
# Add to ~/.bashrc if not present:
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
fi
Apply changes:
source ~/.bashrc
# Or log out and log back in
Verify It's Working
# Try systemctl service completion:
systemctl restart [Tab][Tab]
# Should show available services
# Try Git branch completion:
git checkout [Tab][Tab]
# Should show branches (if in a git repo)
Advanced Completions with bash-completion
With bash-completion installed, you get intelligent completion for many commands.
systemctl Completion
Complete service names:
systemctl status [Tab][Tab]
nginx.service sshd.service httpd.service firewalld.service
systemctl restart ssh[Tab]
systemctl restart sshd.service
Complete systemctl commands:
systemctl [Tab][Tab]
start stop restart reload enable disable status is-active
SSH Completion
Complete hostnames from ~/.ssh/known_hosts and /etc/hosts:
ssh [Tab][Tab]
user@192.168.1.100 user@server1 user@webserver
ssh user@web[Tab]
ssh user@webserver
Git Completion
Complete Git commands:
git [Tab][Tab]
add branch checkout commit diff log merge pull push status
git che[Tab]
git checkout
Complete branch names:
git checkout [Tab][Tab]
main develop feature/new-login bugfix/issue-123
git checkout fea[Tab]
git checkout feature/new-login
Complete remote names:
git push [Tab][Tab]
origin upstream
git push ori[Tab]
git push origin
apt/dnf Package Completion
Complete package names:
# Ubuntu/Debian
sudo apt install vim-[Tab][Tab]
vim-common vim-runtime vim-gtk3 vim-nox
# RHEL/CentOS
sudo dnf install vim-[Tab][Tab]
vim-common vim-enhanced vim-minimal
Docker Completion
Complete Docker commands:
docker [Tab][Tab]
build exec images logs ps pull run start stop
docker ex[Tab]
docker exec
Complete container names:
docker exec -it [Tab][Tab]
webserver database redis_cache
docker exec -it web[Tab]
docker exec -it webserver
make Completion
Complete Makefile targets:
# In a directory with a Makefile
make [Tab][Tab]
all build clean install test
make c[Tab]
make clean
Man Page Completion
Complete man page names:
man sys[Tab][Tab]
sysctl systemctl systemd system
man systemc[Tab]
man systemctl
User and Group Completion
Complete usernames:
su - [Tab][Tab]
root user1 centos9 admin
chown [Tab][Tab]
root user1 centos9 admin
Complete group names:
chgrp [Tab][Tab]
root wheel users docker
How bash-completion Works
bash-completion works through completion scripts stored in specific directories:
Completion Script Locations
System-wide completions:
/usr/share/bash-completion/completions/
View available completions:
ls /usr/share/bash-completion/completions/ | head -20
git
ssh
systemctl
docker
make
apt
dnf
tar
rsync
Each file is a completion script for that specific command.
Completion Functions
Completion scripts define bash functions that tell bash how to complete arguments for specific commands.
Example: View the systemctl completion script:
cat /usr/share/bash-completion/completions/systemctl | head -20
These scripts use bash's complete built-in to register completion behavior.
Customizing Tab Completion
You can customize Tab completion behavior through bash options and readline settings.
Case-Insensitive Completion
Make Tab completion case-insensitive:
Add to ~/.inputrc:
set completion-ignore-case on
Apply changes:
bind -f ~/.inputrc
# Or start a new shell
Now you can type:
cd desk[Tab]
cd Desktop/ # Works even though you typed lowercase
Show All Completions Immediately
Instead of beeping when multiple matches exist, show them immediately:
Add to ~/.inputrc:
set show-all-if-ambiguous on
Now a single Tab press shows all matches instead of requiring two Tab presses.
Colored Completion
Show completion matches with colors (like ls --color):
Add to ~/.inputrc:
set colored-stats on
Visible Bell Instead of Audible
If Tab completion can't find a match, show a visual flash instead of beeping:
Add to ~/.inputrc:
set bell-style visible
Complete Command Suggestions
Show suggestions as you type (like fish shell):
Add to ~/.inputrc:
set show-all-if-unmodified on
set menu-complete-display-prefix on
Creating Custom Completion Scripts
You can create your own completion scripts for custom commands or scripts.
Basic Completion Example
Create a completion for a custom script that takes specific arguments:
# Create a simple completion function
_my_script_completion() {
local cur=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $(compgen -W "start stop restart status" -- $cur) )
}
# Register the completion
complete -F _my_script_completion my_script
Now when you type:
my_script [Tab][Tab]
start stop restart status
Save Custom Completions
Create a file: ~/.bash_completion.d/my_completions
mkdir -p ~/.bash_completion.d
cat > ~/.bash_completion.d/my_completions << 'EOF'
# Custom completion for my_script
_my_script_completion() {
local cur=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $(compgen -W "start stop restart status" -- $cur) )
}
complete -F _my_script_completion my_script
EOF
Load it in ~/.bashrc:
# Add to ~/.bashrc
if [ -d ~/.bash_completion.d ]; then
for file in ~/.bash_completion.d/*; do
[ -r "$file" ] && source "$file"
done
fi
Apply:
source ~/.bashrc
File-Based Completion
Create completion that suggests files with specific extensions:
# Complete only .conf files
_myconfig_completion() {
local cur=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $(compgen -f -X '!*.conf' -- $cur) )
}
complete -F _myconfig_completion myconfig
Practical Tab Completion Tips
Tip 1: Complete Paths Incrementally
Build paths piece by piece:
cd /v[Tab]/l[Tab]/au[Tab]
# Expands to:
cd /var/log/audit/
Tip 2: Use Tab to Verify Files Exist
Before running a command, use Tab to verify the file exists:
cat important_fi[Tab]
# If it doesn't complete, the file doesn't exist
Tip 3: Discover Command Options
Even without bash-completion, you can discover files and directories:
ls /etc/sys[Tab][Tab]
sysconfig/ sysctl.d/ systemd/
Tip 4: Escape Special Characters
Tab completion automatically escapes special characters:
# File name: "my file with spaces.txt"
cat my[Tab]
cat my\ file\ with\ spaces.txt
Tip 5: Complete Multiple Arguments
Use Tab for each argument:
cp /etc/hos[Tab] /tmp/hos[Tab]
cp /etc/hosts /tmp/hosts.backup
Tip 6: Use Tab with Wildcards
Combine Tab with wildcards:
ls *.tx[Tab]
# Completes to *.txt if that's the only match
Common Tab Completion Shortcuts
| Keys | Action |
|------|--------|
| Tab | Complete or show matches (once) |
| Tab Tab | Show all matches |
| Esc Tab | Same as Tab Tab (alternative) |
| Alt-? | Show possible completions |
| Alt-* | Insert all possible completions |
| Ctrl-x / | List possible filename completions |
Best Practices for Tab Completion
1. Always Use Tab for Long Paths
Never type full paths when you can use Tab:
# Bad (tedious):
vim /etc/systemd/system/multi-user.target.wants/sshd.service
# Good (fast):
vim /e[Tab]/sys[Tab]/sys[Tab]/m[Tab]/ss[Tab]
2. Double-Tab to Explore
When unsure what's available, double-Tab to explore:
systemctl [Tab][Tab]
# See all systemctl subcommands
ls /var/[Tab][Tab]
# See all directories in /var
3. Install bash-completion on Servers
Always install bash-completion on servers you manage:
sudo dnf install bash-completion
It dramatically improves productivity.
4. Learn Your Most-Used Completions
Focus on completing:
- Commands you frequently type
- Long file paths
- Service names
- Package names
- Git branches
5. Combine with History
Use Tab completion with history expansion:
!vim[Tab]
# Completes to your last vim command
vim /etc/ssh/sshd_config
Troubleshooting Tab Completion
Problem 1: Tab Completion Not Working
Symptoms: Tab key just inserts a tab character or does nothing.
Solutions:
# 1. Check if bash-completion is installed
dpkg -l | grep bash-completion # Debian/Ubuntu
rpm -qa | grep bash-completion # RHEL/CentOS
# 2. Install it if missing
sudo apt install bash-completion # Debian/Ubuntu
sudo dnf install bash-completion # RHEL/CentOS
# 3. Reload your shell
source ~/.bashrc
Problem 2: Completion Shows Wrong Results
Symptoms: Completion suggests files instead of command-specific options.
Cause: bash-completion not installed or not loaded.
Solution:
# Verify bash-completion is loaded
type _init_completion
# Should output: _init_completion is a function
# If not, add to ~/.bashrc:
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
fi
source ~/.bashrc
Problem 3: Slow Tab Completion
Symptoms: Tab completion takes several seconds.
Causes: Network-mounted filesystems, slow disk, or complex completion scripts.
Solutions:
# 1. Disable completion for slow commands
complete -r slow_command
# 2. Reduce bash-completion scope
# Edit ~/.bashrc and comment out slow completions
Problem 4: Case-Sensitive Issues
Symptoms: Tab completion doesn't work with different case.
Solution: Enable case-insensitive completion in ~/.inputrc:
set completion-ignore-case on
Tab Completion Command Reference
| Command/Setting | Description |
|----------------|-------------|
| Tab | Attempt to complete current word |
| Tab Tab | Show all possible completions |
| complete -p | Show all completion settings |
| complete -r command | Remove completion for command |
| compgen -c | List all available commands |
| compgen -d | List directories |
| compgen -f | List files |
| compgen -v | List variables |
| bind -p | Show all readline keybindings |
Practice Labs
Let's practice Tab completion with hands-on exercises.
Lab 1: Basic Command Completion
Task: Type "sys" and use Tab completion to complete to "systemctl".
Solution
sys[Tab]
# Should complete to:
systemctl
Lab 2: Double Tab to See Options
Task: Type "user" and press Tab twice to see all commands starting with "user".
Solution
user[Tab][Tab]
# Shows:
useradd userdel usermod users
Lab 3: Complete File Names
Task: Create a file called "test_completion.txt", then use Tab to complete "cat test" to view it.
Solution
touch test_completion.txt
cat test_c[Tab]
cat test_completion.txt
Lab 4: Complete Directory Paths
Task: Use Tab completion to navigate to /var/log.
Solution
cd /v[Tab]/l[Tab]
cd /var/log/
Lab 5: Complete Hidden Files
Task: In your home directory, use Tab to complete and view your .bash_history file.
Solution
cat ~/.bash_h[Tab]
cat ~/.bash_history
Lab 6: Variable Name Completion
Task: Use Tab completion to see all variables starting with "HIST".
Solution
echo $HIST[Tab][Tab]
# Shows:
$HISTCMD $HISTCONTROL $HISTFILE $HISTFILESIZE $HISTSIZE
Lab 7: Long File Name Completion
Task: Create a file with a very long name and use Tab to complete it when removing it.
Solution
touch this_is_a_very_long_filename_for_testing_tab_completion.txt
rm thi[Tab]
rm this_is_a_very_long_filename_for_testing_tab_completion.txt
Lab 8: Check if bash-completion is Installed
Task: Check whether bash-completion is installed on your system.
Solution
# For Debian/Ubuntu:
dpkg -l | grep bash-completion
# For RHEL/CentOS:
rpm -qa | grep bash-completion
# Or check the directory:
ls /usr/share/bash-completion/
Lab 9: Install bash-completion
Task: If bash-completion is not installed, install it.
Solution
# Ubuntu/Debian:
sudo apt update
sudo apt install bash-completion
# CentOS/RHEL:
sudo dnf install bash-completion
# Reload bash:
source ~/.bashrc
Lab 10: Test systemctl Completion
Task: If bash-completion is installed, use Tab to see available services when using systemctl restart.
Solution
systemctl restart [Tab][Tab]
# Should show available services like:
# sshd.service nginx.service httpd.service ...
Lab 11: Complete systemctl Commands
Task: Type systemctl followed by a space, then press Tab twice to see available systemctl commands.
Solution
systemctl [Tab][Tab]
# Shows:
# start stop restart reload enable disable status ...
Lab 12: Explore /etc Directory
Task: Use Tab completion to see what directories are in /etc that start with "sys".
Solution
ls /etc/sys[Tab][Tab]
# Shows:
# sysconfig/ sysctl.d/ systemd/
Lab 13: Complete Multiple Arguments
Task: Use Tab completion to copy /etc/hosts to /tmp/hosts.backup.
Solution
cp /etc/hos[Tab] /tmp/hos[Tab]
# Type "t.b" and Tab:
cp /etc/hosts /tmp/hosts.backup
Lab 14: Enable Case-Insensitive Completion
Task: Enable case-insensitive Tab completion for your session.
Solution
# Create or edit ~/.inputrc
echo "set completion-ignore-case on" >> ~/.inputrc
# Apply changes:
bind -f ~/.inputrc
# Test it:
cd desk[Tab]
# Should complete to Desktop/ even with lowercase
Lab 15: View All Completion Settings
Task: Display all current Tab completion settings.
Solution
complete -p
# Shows all registered completions
# Or view completions directory:
ls /usr/share/bash-completion/completions/
Lab 16: Create a Simple Custom Completion
Task: Create a completion for a fictional command called "myapp" that completes with "start", "stop", and "restart".
Solution
# Define the completion function
_myapp_completion() {
local cur=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $(compgen -W "start stop restart" -- $cur) )
}
# Register it
complete -F _myapp_completion myapp
# Test it:
myapp [Tab][Tab]
# Shows: start stop restart
Lab 17: Tab Complete with Wildcards
Task: In a directory with multiple .txt files, use Tab to complete ls *.txt.
Solution
# Create test files:
touch file1.txt file2.txt file3.txt
# Use completion:
ls *.t[Tab]
# Completes to:
ls *.txt
Lab 18: Verify Completion Scripts Exist
Task: Check which completion scripts are available for common commands.
Solution
ls /usr/share/bash-completion/completions/ | grep -E "git|ssh|systemctl|docker"
# Shows available completion scripts for these commands
Lab 19: Complete User Names
Task: Use Tab completion with the su command to see available users.
Solution
su - [Tab][Tab]
# Shows available users:
# root user1 centos9 ...
Lab 20: Navigate Deeply Nested Directories
Task: Use Tab completion to navigate to /var/log/audit efficiently.
Solution
cd /v[Tab]/l[Tab]/au[Tab]
# Completes to:
cd /var/log/audit/
Key Takeaways
-
Tab Completion Saves Time: Single most important productivity feature in bash
-
Single vs Double Tab:
- One Tab: Complete if unique match
- Two Tabs: Show all possible matches
-
Works For:
- Command names
- File and directory names
- Paths
- Variable names (with $)
-
bash-completion Package: Provides intelligent, context-aware completion for hundreds of commands
-
Installation:
- Ubuntu/Debian:
sudo apt install bash-completion - RHEL/CentOS:
sudo dnf install bash-completion
- Ubuntu/Debian:
-
Advanced Completions (with bash-completion):
- systemctl services
- Git branches
- Package names
- SSH hosts
- Docker containers
-
Customization: Use
~/.inputrcfor case-insensitive and other behaviors -
Custom Completions: Create your own with
completecommand -
Always Enabled: Tab completion is always available in bash
-
Best Practice: Use Tab for everything—commands, files, paths, arguments
What's Next?
You now understand how to leverage Tab completion to dramatically speed up your command-line workflow. In the next post, Part 50: Understanding Shell Variables, we'll learn how to:
- Understand what variables are in bash
- Create and use variables
- Distinguish between local and environment variables
- Work with important system variables (PATH, HOME, USER, SHELL)
- Use
exportto make variables available to child processes - View all variables with
envandprintenv - Modify your PATH to add custom directories
- Use variables in scripts and commands
Variables are fundamental to bash scripting and system configuration. Combined with the skills you've learned so far, you'll be able to customize your shell environment and write powerful scripts. See you in the next post!

