Anyone who spends real time in a terminal eventually gets tired of typing the same long command over and over. Maybe it’s git status, or a docker command with six flags, or a find invocation you can never quite remember. Bash aliases solve this in the simplest way possible: give a short name to a longer command, once, and use the short name forever after. It’s a small feature, but it’s one of the highest-value, lowest-effort habits you can build into your workflow.
This guide covers everything from your first alias to advanced patterns, functions as an alternative, and how to manage a growing collection of them properly.
What Is a Bash Alias?
An alias is a shorthand that Bash substitutes for a longer command before execution. It’s purely textual substitution — Bash sees you type the alias name and replaces it with the defined command before doing anything else.
alias ll='ls -alF'
After running this, typing ll behaves exactly as if you’d typed ls -alF.
Creating a Temporary Alias
alias gs='git status'
alias gp='git push'
alias update='sudo apt update && sudo apt upgrade -y'
These aliases exist only for the current shell session — close the terminal, and they’re gone. That’s fine for quick experiments, but for anything you want permanently, it needs to go into a startup file.
Making Aliases Permanent
Bash reads certain startup files when a shell begins. For interactive, non-login shells (most terminal windows), that’s ~/.bashrc. For login shells, it’s typically ~/.bash_profile or ~/.profile, which conventionally source ~/.bashrc as well.
# Add to ~/.bashrc
echo "alias ll='ls -alF'" >> ~/.bashrc
# Reload the current shell's config without restarting the terminal
source ~/.bashrc
How this works internally: every time you open a new interactive terminal, Bash automatically reads and executes ~/.bashrc line by line, which is why anything defined there — aliases, functions, environment variables — becomes available in every new session without manual setup.
Common, Genuinely Useful Aliases
# Navigation
alias ..='cd ..'
alias ...='cd ../..'
alias ~='cd ~'
# Listing
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias lt='ls -alFt' # sorted by modification time
# Safety nets — confirm before overwriting or deleting
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Git shortcuts
alias gs='git status'
alias ga='git add'
alias gc='git commit -m'
alias gp='git push'
alias gl='git log --oneline --graph --decorate'
# System
alias update='sudo apt update && sudo apt upgrade -y'
alias ports='sudo netstat -tulanp'
alias df='df -h'
alias free='free -h'
# Networking
alias myip='curl -s ifconfig.me'
# Directory shortcuts
alias proj='cd ~/projects'
Viewing and Removing Aliases
# List all currently defined aliases
alias
# Show the definition of a specific alias
alias ll
# Remove an alias for the current session
unalias ll
# Remove all aliases for the current session
unalias -a
To remove one permanently, delete or comment out its line in ~/.bashrc and re-source the file.
Aliases with Arguments — Where They Fall Short
A common early mistake is expecting an alias to accept arguments the way a function or script does:
alias greet='echo "Hello,"'
greet World
This actually works by accident — aliases append anything typed after them to the substituted command, so greet World becomes echo "Hello," World. But this only works for arguments tacked onto the end. You cannot use an alias to insert an argument in the middle of a command, or do any conditional logic. For that, you need a function.
When to Use a Function Instead
Functions are far more powerful than aliases and should be your default choice once a command needs any logic, argument placement flexibility, or multiple steps.
# A function instead of an alias — supports proper argument handling
mkcd() {
mkdir -p "$1" && cd "$1"
}
mkcd new_project # creates the directory AND moves into it
# A function with conditional logic
extract() {
if [[ -f "$1" ]]; then
case "$1" in
*.tar.gz) tar xzf "$1" ;;
*.tar.bz2) tar xjf "$1" ;;
*.zip) unzip "$1" ;;
*.gz) gunzip "$1" ;;
*) echo "Unknown archive type: $1" ;;
esac
else
echo "File not found: $1"
fi
}
Functions, like aliases, belong in ~/.bashrc to be available in every new shell session.
Organizing a Growing Alias Collection
Once you accumulate dozens of aliases, dumping them all directly into ~/.bashrc gets messy. A cleaner pattern is a separate file, sourced from ~/.bashrc:
# ~/.bash_aliases
alias ll='ls -alF'
alias gs='git status'
# ... etc
# In ~/.bashrc
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
Many distributions (Debian/Ubuntu in particular) already include this exact snippet in the default ~/.bashrc, so ~/.bash_aliases often works out of the box without any changes.
Real-World Use Cases
Project-Specific Shortcuts
alias dstart='docker compose up -d'
alias dstop='docker compose down'
alias dlogs='docker compose logs -f'
alias dprune='docker system prune -af'
Kubernetes Shortcuts
alias k='kubectl'
alias kgp='kubectl get pods'
alias kgs='kubectl get svc'
alias kaf='kubectl apply -f'
Safer Defaults for Destructive Commands
alias rm='rm -I --preserve-root'
-I (capital i) prompts only once for more than three files, rather than once per file like -i, striking a balance between safety and not being annoying.
Quick Environment Switching
alias prodenv='export ENV=production; echo "Switched to PRODUCTION"'
alias devenv='export ENV=development; echo "Switched to development"'
Best Practices
- Keep aliases short, memorable, and mnemonic —
gsforgit statussticks because it reads naturally. - Don’t override standard command names in ways that could surprise you or others using your machine (overriding
rmwith-iis generally accepted; overridingcdto do something entirely different is asking for confusion). - Move anything needing arguments in the middle, conditionals, or multiple logical steps into a function instead of forcing it into an alias.
- Organize aliases into a dedicated
~/.bash_aliasesfile once you have more than a handful. - Comment your aliases file, especially for anything non-obvious, so future-you (or teammates using a shared dotfiles repo) understands the intent.
- Check for naming collisions with existing commands using
type aliasnamebefore defining a new one.
Security Considerations
- Be cautious aliasing common commands (
ls,cd,sudo) in ways that could mask unexpected behavior — a malicious or buggy alias definition sourced from an untrusted dotfiles repo could silently redirect a trusted command to something harmful. - Never source
~/.bashrcor alias files from untrusted sources without reviewing them first — since alias definitions execute as part of normal shell startup, a hostile alias file is a viable attack vector on shared or downloaded dotfiles. - Avoid aliasing
sudoitself or embedding credentials inside alias definitions. - If sharing dotfiles publicly (e.g., a GitHub dotfiles repo), audit them for anything environment-specific like internal hostnames, IPs, or tokens before publishing.
Optimization Tips
- Aliases have effectively zero performance cost — they’re a simple text substitution done by the shell itself, not a subprocess. Prefer them over tiny wrapper scripts for anything that doesn’t need logic.
- For frequently-used multi-step operations, a function is often barely slower than an alias (still no subprocess spawned for the function definition itself) while being significantly more flexible — there’s rarely a real performance reason to prefer an alias over a function once complexity grows.
- Keep
~/.bashrcitself lean; a bloated startup file with hundreds of unused aliases or slow logic can noticeably delay new terminal startup. Load rarely-used alias sets conditionally or lazily if this becomes an issue.
Troubleshooting Common Issues
Problem: A newly added alias doesn’t work. Confirm you sourced the file (or opened a new terminal) after adding it — aliases only apply to shells started (or refreshed) after the definition was added.
Problem: The alias works in one terminal but not another. Check whether the alias was defined only temporarily in the current session (not saved to ~/.bashrc), or whether it was added to a file that isn’t actually being sourced by your shell’s startup sequence (login vs. non-login shell differences are a common cause).
Problem: An alias silently doesn’t apply inside a script. By default, aliases are not expanded in non-interactive shells (like scripts) unless you explicitly enable it with shopt -s expand_aliases near the top of the script. In general, prefer functions over aliases for anything used inside scripts.
Problem: Two aliases seem to conflict. The last definition sourced wins — check for duplicate or conflicting definitions across ~/.bashrc, ~/.bash_aliases, and any other sourced files.
Common Mistakes
- Trying to pass arguments into the middle of an alias instead of switching to a function.
- Forgetting to
source ~/.bashrcafter adding a new alias and assuming it’s broken. - Overriding fundamental commands in ways that surprise collaborators using a shared machine or shared dotfiles.
- Letting the alias file grow unmanaged without comments or organization, making it hard to maintain.
- Assuming aliases work inside scripts by default, without enabling
expand_aliases.
Frequently Asked Questions
What’s the difference between an alias and a function? An alias is simple text substitution and only works cleanly when arguments are appended at the end. A function is a full shell construct that can take positional arguments anywhere, use conditionals and loops, and return values — use functions for anything beyond trivial shorthand.
Do aliases work in scripts? Not by default. Non-interactive shells don’t expand aliases unless shopt -s expand_aliases is set explicitly, and even then, an alias must be defined before it’s used in the same script. Functions don’t have this limitation and are generally the better choice inside scripts.
Where should I put my aliases — .bashrc or .bash_profile? For nearly everyone using interactive terminal sessions, ~/.bashrc is correct, since that’s what’s read for interactive non-login shells (the common case for terminal emulators). .bash_profile matters mainly for login shells (like an SSH session), and conventionally sources .bashrc itself to keep behavior consistent either way.
Can I share my aliases across multiple machines? Yes — a common approach is keeping ~/.bash_aliases (or a full dotfiles setup) in a version-controlled repository and symlinking it into place on each machine.
Summary
Bash aliases are one of the simplest, highest-leverage customizations you can make to your shell — a few minutes spent turning your most-repeated commands into short, memorable shortcuts pays for itself almost immediately. Start with aliases for your most common commands, graduate to functions once you need arguments or logic, and keep everything organized in ~/.bash_aliases sourced from ~/.bashrc so your setup stays clean and portable across machines.
References
- GNU Bash Manual — Aliases: https://www.gnu.org/software/bash/manual/bash.html#Aliases
- GNU Bash Manual — Bash Startup Files: https://www.gnu.org/software/bash/manual/bash.html#Bash-Startup-Files
- GNU Bash Manual — Shell Functions: https://www.gnu.org/software/bash/manual/bash.html#Shell-Functions
- GNU Bash Manual — The Shopt Builtin: https://www.gnu.org/software/bash/manual/bash.html#The-Shopt-Builtin