alias ll='ls -alh' — that's the basic idea. Give a long command a short name. Write it in .bashrc or .zshrc to make it permanent, and use shell functions when you need arguments.
If you work in the terminal regularly, you've definitely typed the same commands dozens of times. git status. docker-compose up -d. cd /home/user/projects/myapp/frontend/src.
All of that can become an alias. This guide covers everything you need to know about the alias command — from the basics to advanced patterns, real-world shortcut collections, and oh-my-zsh integration.
What is an alias?
An alias is a shortcut: you give a long or complex command a shorter name, and use that name instead. macOS and most Linux distros come with several aliases already defined. See the GNU Bash Manual — Aliases for the full specification. Run alias with no arguments to see them:
alias
Typical output on Ubuntu:
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
So ll is a shortcut for ls -alF. Two characters instead of eight, and you get a detailed listing with colors and indicators.
Basic syntax
alias name='command string'
A few things to keep in mind:
- No spaces around
=— that's a syntax error - Wrap the command in single or double quotes if it contains spaces or options
- Single quotes prevent variable expansion; double quotes allow it
Quick examples to get started:
alias ll='ls -alh --color=auto'
alias la='ls -A'
alias ..='cd ..'
alias ...='cd ../..'
alias gs='git status'
Run these in your terminal and they work immediately — but only for the current session. Close the terminal and they're gone.
Making aliases permanent: .bashrc and .zshrc
To keep your aliases across sessions, write them to your shell's config file.
First, check which shell you're using:
echo $SHELL
- bash →
~/.bashrc(interactive shell) or~/.bash_profile(login shell) - zsh →
~/.zshrc
Open the file in your preferred editor:
# vim
vim ~/.bashrc
# nano (beginner-friendly)
nano ~/.bashrc
# VS Code
code ~/.bashrc
Add your aliases at the bottom. I find it helpful to group them with a comment:
# ===========================
# My Aliases
# ===========================
# Navigation
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias home='cd ~'
alias proj='cd ~/projects'
# ls shortcuts
alias ll='ls -alh --color=auto'
alias la='ls -A --color=auto'
alias lt='ls -lt --color=auto' # sort by time
alias lz='ls -lS --color=auto' # sort by size
# Common shortcuts
alias c='clear'
alias h='history'
alias q='exit'
alias reload='source ~/.bashrc' # or source ~/.zshrc for zsh
After saving, apply the changes to the current session:
source ~/.bashrc
# or
. ~/.bashrc
Useful alias collections
Git
If you use Git daily, these will save a significant amount of typing:
# Basic Git
alias gs='git status'
alias ga='git add'
alias gaa='git add .'
alias gc='git commit -m'
alias gca='git commit -am'
alias gp='git push'
alias gpl='git pull'
alias gd='git diff'
alias gl='git log --oneline --graph --decorate'
alias gb='git branch'
alias gco='git checkout'
alias gcb='git checkout -b'
alias gst='git stash'
alias gstp='git stash pop'
# Compound operations
alias gpush='git push origin $(git branch --show-current)'
alias gundo='git reset --soft HEAD~1' # undo last commit, keep changes
alias gclean='git restore .' # discard all working tree changes (modern syntax, Git 2.23+)
Docker and Docker Compose
alias d='docker'
alias dc='docker compose'
alias dcu='docker compose up -d'
alias dcd='docker compose down'
alias dcr='docker compose restart'
alias dcl='docker compose logs -f'
alias dps='docker ps'
alias dpsa='docker ps -a'
alias dclean='docker system prune -f'
# Enter a running container
dexec() {
docker exec -it "$1" bash
}
System administration
# Network
alias myip='curl -s ifconfig.me'
alias localip='ip addr show | grep "inet " | grep -v 127.0.0.1'
# Disk and memory
alias df='df -h'
alias du='du -sh'
alias free='free -h'
# Process search
alias psg='ps aux | grep' # usage: psg nginx
# Check which process is using a port
portcheck() {
lsof -i :"$1"
}
# File search
alias ff='find . -name' # usage: ff "*.log"
Development
# Node.js / npm
alias ni='npm install'
alias nid='npm install --save-dev'
alias nr='npm run'
alias ns='npm start'
alias nt='npm test'
alias nb='npm run build'
# Python
alias py='python3'
alias pip='pip3'
alias venv='python3 -m venv venv && source venv/bin/activate'
alias activate='source venv/bin/activate'
# Quick local HTTP server
alias serve='python3 -m http.server 8080'
Shell functions: when aliases aren't enough
Aliases don't handle arguments very well. When you need to pass arguments, use a shell function instead. They go in the same .bashrc / .zshrc file:
# Make a directory and cd into it immediately
mkcd() {
mkdir -p "$1" && cd "$1"
}
# Search file contents recursively
# (named rgfind to avoid shadowing the system fgrep command)
rgfind() {
grep -r "$1" . --include="$2"
}
# usage: rgfind "TODO" "*.js"
# Create a timestamped backup of a file
bak() {
cp "$1" "$1.bak_$(date +%Y%m%d_%H%M%S)"
}
# usage: bak config.json → creates config.json.bak_20260227_143022
# Kill whatever is running on a port
killport() {
lsof -t -i:"$1" | xargs kill -9
}
# usage: killport 3000
oh-my-zsh: get hundreds of aliases instantly
If you use zsh with oh-my-zsh, you can enable plugins that add a large number of well-designed aliases without having to write them yourself.
Edit the plugins=(...) line in ~/.zshrc:
plugins=(
git
docker
docker-compose
npm
python
z
)
The git plugin alone adds 150+ aliases — gst for git status, gco for git checkout, and so on. You can check the full list of git plugin aliases or run alias | grep ^g to see what's active.
The z plugin lets you jump to any previously visited directory by typing part of its name. A more powerful alternative is zoxide, which is also available as an oh-my-zsh plugin:
z proj # jumps to ~/projects if you've been there before
Managing your aliases
Check what a specific alias does
alias gs
# output: alias gs='git status'
Temporarily bypass an alias
If a command is shadowed by an alias and you want to run the original, prefix it with \:
# Even if ls is aliased, this runs the real ls with no color
\ls
Delete an alias
unalias gs # remove the gs alias
unalias -a # remove ALL aliases (use with caution)
Safe workflow for editing .bashrc
# Back up first
cp ~/.bashrc ~/.bashrc.backup
# Edit
vim ~/.bashrc
# Check for syntax errors (bash only)
bash -n ~/.bashrc
# Apply if no errors
source ~/.bashrc
Advanced techniques
Debug aliases with type and command -v
When a command doesn't behave as expected, check whether it's an alias, a function, or a binary with type:
type ls
# ls is aliased to 'ls --color=auto'
type mkcd
# mkcd is a function
type grep
# grep is aliased to 'grep --color=auto'
type curl
# curl is /usr/bin/curl
In scripts, command -v is more portable for checking whether a command exists:
if command -v docker &>/dev/null; then
alias dc='docker compose'
fi
Conditional aliases by OS
When sharing the same .bashrc across macOS and Linux, some commands differ between platforms. Use $OSTYPE to branch:
case "$OSTYPE" in
linux*)
alias open='xdg-open'
alias pbcopy='xclip -selection clipboard'
alias pbpaste='xclip -selection clipboard -o'
;;
darwin*)
alias ls='ls -G'
alias readlink='greadlink' # brew install coreutils
;;
esac
One set of dotfiles, works on both platforms.
Separate alias file
As your alias collection grows, keep .bashrc clean by moving aliases to a dedicated file:
# Add to the end of ~/.bashrc
if [ -f ~/.aliases ]; then
source ~/.aliases
fi
Put all aliases in ~/.aliases. This also makes sharing dotfiles across a team easier to manage.
zsh only: global aliases (alias -g)
In zsh, alias -g defines aliases that expand anywhere in a command — not just at the beginning. Useful for shortening pipe chains:
# zsh only
alias -g L='| less'
alias -g G='| grep'
alias -g H='| head'
alias -g T='| tail'
alias -g C='| wc -l'
alias -g J='| jq .'
alias -g S='| sort'
alias -g U='| sort -u'
Usage:
ps aux G nginx # → ps aux | grep nginx
cat access.log C # → cat access.log | wc -l
curl -s api.example.com/data J # → ... | jq .
This feature doesn't exist in bash. Bash users can achieve similar results with functions.
zsh only: suffix aliases (alias -s)
zsh's alias -s assigns a default program to file extensions:
# zsh only
alias -s json='code'
alias -s md='code'
alias -s log='less'
alias -s py='python3'
alias -s html='open'
# Just type the filename to open it with the assigned program
config.json # → code config.json
README.md # → code README.md
error.log # → less error.log
Common issues
"command not found" after adding an alias
You probably forgot to run source ~/.bashrc. Also check for typos — make sure there are no spaces around the = sign.
alias | grep aliasname
Paths with spaces cause errors
Always quote paths that contain spaces:
# Wrong
alias mydir='cd /home/user/My Projects'
# Right
alias mydir='cd "/home/user/My Projects"'
Using one alias inside another
Aliases are only expanded one level deep by default. If you need to reference another alias inside an alias, use a function instead.
Related Articles
- Modern Rust CLI Tools — exa, bat, fd, ripgrep — the modern tools you'll want to alias
- tmux Practical Guide — tmux + aliases for an even more efficient terminal workflow
- fzf Practical Guide — combine fzf with aliases for instant fuzzy search
- CLI Toolkit — the big picture of CLI tools and when to use each
FAQ
What's the difference between an alias and a shell function?
An alias is a simple text substitution — it can't handle arguments flexibly or include logic like conditionals and loops. Use aliases for straightforward shortcuts like alias gs='git status'. Use functions when you need arguments: mkcd() { mkdir -p "$1" && cd "$1"; }.
How do I debug an alias that isn't working?
Start with type alias_name to check its current state. If it says "not found," you probably forgot to run source ~/.bashrc. Check if the alias is defined with alias | grep alias_name, and validate your config file syntax with bash -n ~/.bashrc.
Are aliases written differently in bash vs zsh?
The basic syntax is identical: alias name='command' works in both. The difference is zsh-exclusive features — alias -g (global aliases) and alias -s (suffix aliases) only work in zsh.
What do I do when I have too many aliases to manage?
Move them to a dedicated file like ~/.aliases and source it from .bashrc with source ~/.aliases. You can also split by category: ~/.aliases_git, ~/.aliases_docker, etc. See the dotfiles management guide for more.
Why don't my aliases work with sudo?
sudo runs commands in a new shell context, so aliases from your current shell don't carry over. Define alias sudo='sudo ' (note the trailing space) — this tells bash to also check for alias expansion on the command that follows sudo.
What happens when oh-my-zsh plugin aliases conflict with mine?
The last definition wins. In .zshrc, your custom aliases are defined after plugins load, so yours typically take priority. Check the current definition with alias | grep alias_name to confirm.
Wrapping Up
Aliases are for two things: commands you type constantly, and options you can never remember. Start with just a few, and add more whenever you catch yourself typing the same thing repeatedly.
Get started right now:
- Run
aliasto see what's already defined - Open
~/.bashrcor~/.zshrcand add your own aliases section - Run
source ~/.bashrcto apply the changes
Once you've built up a solid set of aliases, move on to shell functions for anything that needs arguments. Over time, your shell config becomes a productivity tool that's tailored exactly to how you work.
Related articles: