Aliases

An alias is a shorthand name you define for a longer command, so you can type ll instead of ls -alF, or gs instead of git status. Aliases are one of the simplest, highest-payoff ways to speed up your day-to-day work at the terminal, once you notice which commands you type over and over. They live entirely inside your shell’s memory: no new program is written to disk, and no new process is created just to define one.

Overview / How Aliases Work

An alias is not a program, a script, or an entry in your PATH — it is a text-substitution rule stored in a table that Bash keeps in memory for the current shell session. When Bash reads a line you typed and is about to parse it into a command, it looks at the very first word. If that word matches a name in the alias table, Bash replaces the word with the alias’s stored text and then re-parses the line as if you had typed the replacement yourself. Only after this substitution does Bash go on to do its normal job: expanding variables, splitting words, and eventually searching PATH (or checking builtins) to find something to execute.

This textual-replacement model explains a lot of alias behavior that otherwise seems strange. Because only the first word of a command line is checked against the alias table, alias ll='ls -alF' lets you type ll /var/log and have it become ls -alF /var/log — the extra argument is simply appended after the substituted text, not inserted into the middle of it. This also means aliases cannot take positional parameters the way a script or function can; you cannot write an alias that rearranges or transforms its arguments. If you need real logic — conditionals, loops, or arguments used more than once — you need a shell function, not an alias.

There is one more subtlety worth knowing: if an alias’s replacement text ends in a trailing space, Bash checks the next word against the alias table too. This is why distributions sometimes define alias sudo='sudo ' — it lets an alias typed immediately after sudo still get expanded, since without the trailing space, alias expansion would stop at sudo itself.

Aliases also only exist for the shell that defined them, and only for as long as that shell is running. Close the terminal and any alias you typed directly at the prompt is gone. To make an alias available every time you open a new terminal, you add the alias command to your shell’s startup file, ~/.bashrc, which Bash reads automatically for every new interactive, non-login shell. Finally, by design, Bash does not expand aliases in non-interactive shells — which includes every script you run with ./script.sh or bash script.sh — unless you explicitly turn that behavior on with shopt -s expand_aliases. Aliases are a convenience for humans typing at a prompt; scripts are expected to spell out real commands so they stay portable and predictable.

Syntax

alias name='command string here'
Form What it does
alias List every alias currently defined in this shell
alias name Print the definition of one specific alias
alias name='command' Define (or redefine) an alias called name
unalias name Remove one alias
unalias -a Remove every alias in the current shell
\command or command command Run command exactly once, ignoring any alias with that name

Quoting the value matters: single quotes ('...') keep the text completely literal, while double quotes ("...") let Bash expand variables and command substitutions immediately, at the moment you define the alias. Almost always you want single quotes so that anything inside the command runs fresh each time the alias is used — see the Common Mistakes section below for what goes wrong otherwise.

Examples

Example 1: a simple shorthand for a long listing

alias ll='ls -alF'
ll

Output:

total 24
drwxr-xr-x 5 ada ada 4096 Aug  3 10:15 ./
drwxr-xr-x 3 ada ada 4096 Aug  1 09:02 ../
-rw-r--r-- 1 ada ada  220 Aug  1 09:02 .bashrc
drwxr-xr-x 8 ada ada 4096 Aug  3 10:15 .git/
-rw-r--r-- 1 ada ada 1519 Aug  3 09:50 README.md

Typing ll expanded to ls -alF before Bash ran anything, so the terminal shows the same detailed listing (all files, long format, trailing / or * markers) you would get from typing the full command by hand.

Example 2: chaining commands in one alias

alias update='sudo apt update && sudo apt upgrade -y'
alias -p | grep update

Output:

alias update='sudo apt update && sudo apt upgrade -y'

An alias’s value can be an entire pipeline or a chain of commands joined with &&, exactly as if you had typed it directly. Now running update refreshes the package index and upgrades every installed package (on RHEL/Fedora, the equivalent alias would use sudo dnf upgrade -y instead). Note that sudo is written inside the alias, in front of each command — not typed in front of the alias name when you run it. Example 3 in Common Mistakes explains why that placement matters.

Example 3: making an alias permanent

cat >> ~/.bashrc << 'EOF'
alias ll='ls -alF'
alias gs='git status'
alias ..='cd ..'
EOF
source ~/.bashrc

An alias typed straight at the prompt lives only in that one shell’s memory. Appending the definitions to ~/.bashrc (note the >>, which appends, not >, which would overwrite the whole file) makes Bash define them automatically in every future interactive shell. Running source ~/.bashrc re-reads the file into the current shell immediately, so you do not have to close and reopen the terminal to start using the new aliases.

How It Works Step by Step

Walking through what happens when you type ll /var/log after defining alias ll='ls -alF':

  1. Bash reads the line you typed and tokenizes it into words: ll and /var/log.
  2. Before doing anything else, Bash checks whether the first word, ll, is a key in its in-memory alias table.
  3. It finds a match, so it substitutes the alias’s stored text, ls -alF, in place of ll. The line is now effectively ls -alF /var/log.
  4. Bash re-parses this expanded line normally: performing variable expansion, word splitting, and globbing on whatever needs it.
  5. Bash searches for how to run ls: first checking if it is a shell keyword or builtin (it is not), then walking the directories listed in $PATH until it finds the executable, typically /usr/bin/ls.
  6. The kernel forks a new child process and execs /usr/bin/ls with the arguments -alF and /var/log. The alias itself is never executed — it only shaped the text before execution began.

Common Mistakes

Mistake 1: double-quoting an alias that should stay literal

alias mydir="echo Current dir: $PWD"

Because the alias value is inside double quotes, Bash expands $PWD immediately, at the moment you type this line — not every time mydir runs. The alias ends up permanently baked with whatever directory you happened to be in when you defined it, so it prints the same (wrong) path no matter where you cd to afterward.

alias mydir='echo "Current dir: $PWD"'

Single-quoting the outer alias value prevents any expansion at definition time. Now $PWD is only expanded when mydir actually runs, so it correctly reports the directory you are in at that moment.

Mistake 2: relying on an alias inside a script

#!/usr/bin/env bash
# WRONG: aliases are not expanded in non-interactive shells by default
ll /var/log

Run this file with bash script.sh and it fails with something like script.sh: line 3: ll: command not found, even though ll works fine when you type it at your prompt. Non-interactive shells — which includes every script — do not read your alias table unless you explicitly enable shopt -s expand_aliases, and even then the alias has to be defined before it is used in the same script.

#!/usr/bin/env bash
set -euo pipefail
ls -alF /var/log

The fix is simply to spell out the real command in the script instead of depending on a personal alias that might not exist on another machine, another user’s account, or in a cron job’s shell.

Mistake 3: forgetting that sudo does not see your aliases

sudo update

If update is an alias you defined for yourself, running sudo update fails with sudo: update: command not found. sudo starts a new shell process to run its target command, and that process does not inherit your interactive shell’s alias table.

alias update='sudo apt update && sudo apt upgrade -y'
update

The fix is to put sudo inside the alias definition, in front of each command that needs it, and then run the alias itself without sudo in front — exactly the pattern used in Example 2.

Best Practices

  • Define all your aliases in ~/.bashrc, grouped under a comment, so they persist across sessions and are easy to find later.
  • Prefer short, memorable names that do not collide with real commands, unless you are intentionally overriding one for safety (for example alias rm='rm -i').
  • Reach for a shell function instead of an alias as soon as you need arguments, conditionals, or more than one line of logic.
  • Never depend on a personal alias inside a script meant to run elsewhere — write the full command instead.
  • Before defining a new alias, check whether the name is already something with type name or alias name, so you know if you are shadowing an existing command.
  • Use \command or command command when you deliberately need to bypass an alias for one invocation.
  • After editing ~/.bashrc, run source ~/.bashrc (or open a new terminal) to pick up the changes.

Practice Exercises

  • Create two aliases, .. for cd .. and ... for cd ../.., add them to ~/.bashrc, and confirm they work in a brand-new terminal window.
  • Create an alias called myip that prints your public IP address using curl, then use type myip to confirm how Bash reports it differently from a real command.
  • Define an alias, remove it with unalias, then try running it again and observe the exact error message Bash gives you.

Summary

  • An alias is a stored text substitution, expanded by Bash before parsing, not a program or a process.
  • Define one with alias name='command', remove one with unalias name, and list them all with alias.
  • Only the first word of a command line triggers alias expansion, and aliases cannot accept positional parameters — use a function for that.
  • Aliases exist only in the defining shell’s memory until you add them to ~/.bashrc to make them permanent.
  • Aliases are not expanded in scripts or by sudo‘s child shell by default, so keep scripts explicit and put sudo inside alias definitions rather than in front of them.