Shell Customization: Aliases, Functions and the Prompt

Intermediate
12 min

Shell Customization: Aliases, Functions and the Prompt

The environment variables lesson explained what .bashrc is. This lesson is about making the shell yours: shortcuts for commands you type fifty times a day, small functions that stitch commands together, a prompt that shows the information you actually need, and the startup-file rules that decide when each setting loads. A well-configured shell removes friction from every task that follows.

Aliases

An alias substitutes one word for a longer command. It is expanded before the rest of the line is parsed, so any extra arguments are appended.

bash
alias ll='ls -alF --color=auto' alias la='ls -A' alias ..='cd ..' alias ...='cd ../..' alias gs='git status' alias gl='git log --oneline --graph --decorate -20' alias ports='ss -tulpn' alias please='sudo' alias rm='rm -i' # safety net alias grep='grep --color=auto'
bash
alias # list all aliases alias ll # show one unalias ll # remove \ls # run the real command, bypassing an alias type ll # "ll is aliased to `ls -alF --color=auto'"

Aliases are stored in memory only; put them in ~/.bashrc (or a separate ~/.bash_aliases that .bashrc sources) to keep them between sessions. Use single quotes so nothing is expanded at definition time.

Functions: When an Alias Is Not Enough

Aliases cannot use arguments in the middle of a command or contain logic. Shell functions can, and they live in the same file.

bash
# make a directory and enter it mkcd() { mkdir -p "$1" && cd "$1" } # back up a file with a timestamp bak() { cp -v "$1" "$1.$(date +%Y%m%d-%H%M%S).bak" } # search running processes by name psg() { ps aux | grep -v grep | grep -i --color=auto "$1" } # universal extractor extract() { case "$1" in *.tar.gz|*.tgz) tar xzf "$1" ;; *.tar.xz) tar xJf "$1" ;; *.zip) unzip "$1" ;; *.gz) gunzip "$1" ;; *) echo "extract: unknown archive type: $1" ;; esac }

Inside a function $1, $2 and $@ are the arguments, exactly as in a script. Always quote them. A function defined in .bashrc is available in every interactive shell but not in scripts, which start clean.

Customizing the Prompt

The prompt is the value of PS1, re-evaluated before every line. Backslash escapes insert live information, and ANSI colour codes must be wrapped in \[ and \] so bash can measure the visible length correctly.

| Escape | Shows | |---|---| | \u | username | | \h | hostname (short) | | \w | current directory, with ~ for home | | \W | basename of the current directory | | \$ | $ for users, # for root | | \t | time, 24-hour | | \n | newline | | \[\e[32m\] … \[\e[0m\] | start green … reset colour |

bash
# Simple two-colour prompt PS1='\[\e[32m\]\u@\h\[\e[0m\]:\[\e[34m\]\w\[\e[0m\]\$ ' # With the current git branch parse_git_branch() { git branch 2>/dev/null | sed -n 's/^\* \(.*\)/ (\1)/p' } PS1='\[\e[32m\]\u@\h\[\e[0m\]:\[\e[34m\]\w\[\e[33m\]$(parse_git_branch)\[\e[0m\]\$ ' # Two-line prompt: path on the first line, a clean second line for typing PS1='\[\e[34m\]\w\[\e[0m\]\n\$ '

The $(parse_git_branch) inside single quotes is evaluated every time the prompt is drawn, which is what you want. Colour codes: 31 red, 32 green, 33 yellow, 34 blue, 35 magenta, 36 cyan; 1;32 for bold green.

Which File Loads When

Bash reads different files depending on how it was started, and this is the most common reason a customization "does not work".

| Shell type | Files read | Examples | |---|---|---| | Login shell | /etc/profile, then the first of ~/.bash_profile, ~/.bash_login, ~/.profile | SSH session, text console | | Interactive non-login | /etc/bash.bashrc, ~/.bashrc | new terminal tab in a desktop | | Non-interactive | only $BASH_ENV if set | scripts, cron |

The convention that makes everything work: put aliases, functions and PS1 in ~/.bashrc, and make sure ~/.profile (or ~/.bash_profile) sources it. Ubuntu's default ~/.profile already does. Environment variables such as PATH belong in ~/.profile so login shells and graphical sessions inherit them.

bash
# ~/.bash_profile on systems that do not have this yet [ -f ~/.bashrc ] && . ~/.bashrc

After editing, run source ~/.bashrc (or . ~/.bashrc) to apply changes in the current shell.

Useful Shell Options

bash
shopt -s autocd # type a directory name to cd into it shopt -s cdspell # correct minor typos in cd shopt -s histappend # append history rather than overwrite on exit shopt -s globstar # ** matches recursively: ls **/*.js HISTSIZE=50000 HISTFILESIZE=100000 HISTCONTROL=ignoreboth # skip duplicates and lines starting with a space export EDITOR=vim set -o vi # vi-style line editing, if you prefer it

Common Mistakes

  • Defining an alias with double quotes and a $(...), which runs once at definition time instead of each use.
  • Naming a function the same as a command you still need (ls() {...}), then losing access to the original. Use command ls inside the function.
  • Forgetting \[ \] around colour codes, which makes line editing jump and wrap incorrectly.
  • Putting PATH changes only in .bashrc, so GUI applications and cron do not see them.
Quick Quiz
Question 1 of 3

Why would you use a function instead of an alias?

Key Takeaways

  • Aliases are text substitutions for frequent commands; define them in ~/.bashrc with single quotes.
  • Functions accept arguments and logic; quote $1 and $@, and use command to call the original program.
  • PS1 builds the prompt from escapes like \u, \h, \w; wrap colour codes in \[ \].
  • Login shells read ~/.profile; interactive shells read ~/.bashrc; have the former source the latter.
  • source ~/.bashrc applies edits immediately; shopt and HIST* variables tune behaviour further.

Next lesson: Shell Scripting Basics — turn sequences of commands into reusable scripts with a shebang, variables and simple control flow.

Shell Customization: Aliases, Functions and the Prompt - Linux & Command Line | CodeYourCraft | CodeYourCraft