Shell Customization
Shell Customization#
Concepts#
Shell Startup Files#
When Bash starts, it reads configuration files — but which files depend on how the shell was started.
Login vs Non-Login Shell#
| Type | When | Example |
|---|---|---|
| Login shell | First shell after authentication | SSH session, TTY login, su - user |
| Non-login shell | Shells opened inside an existing session | Opening a terminal in the desktop, running bash |
Interactive vs Non-Interactive Shell#
| Type | When | Example |
|---|---|---|
| Interactive | You type commands at a prompt | Terminal window, SSH session |
| Non-interactive | Runs a script, no prompt | bash script.sh, cron jobs |
Which Files Are Read?#
Login shell (interactive):
/etc/profile → ~/.bash_profile OR ~/.bash_login OR ~/.profile (first found)
Non-login shell (interactive):
/etc/bash.bashrc → ~/.bashrc
Non-interactive shell (scripts):
$BASH_ENV (if set)
In practice, on Ubuntu and Debian, ~/.profile sources ~/.bashrc:
# Default ~/.profile on Ubuntu/Debian contains:
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
This means .bashrc runs in almost every interactive session. Put your customizations there.
Summary#
| File | What to put in it |
|---|---|
~/.bashrc |
Aliases, functions, prompt, shell options — anything interactive |
~/.profile |
Environment variables (PATH, EDITOR, LANG) — login-time settings |
~/.bash_profile |
Rarely needed on Ubuntu/Debian (.profile is used instead) |
/etc/profile |
System-wide login settings (don’t edit unless you’re root) |
/etc/bash.bashrc |
System-wide interactive shell settings |
Environment Variables#
Environment variables are key-value pairs available to all processes. Child processes inherit them from their parent.
# View all environment variables
env
printenv
# View a specific variable
echo $HOME
echo $PATH
echo $SHELL
# Set a variable (current shell only)
MY_VAR="hello"
# Export it (available to child processes)
export MY_VAR="hello"
# Unset a variable
unset MY_VAR
# Common variables
echo $USER # current username
echo $HOME # home directory
echo $PWD # current directory
echo $SHELL # default shell
echo $EDITOR # preferred text editor
echo $LANG # language/locale
echo $TERM # terminal type
To make a variable permanent, add the export line to ~/.profile (for login shells) or ~/.bashrc (for all interactive shells):
# In ~/.bashrc or ~/.profile
export EDITOR="vim"
export VISUAL="vim"
The PATH Variable#
PATH is a colon-separated list of directories the shell searches for commands:
echo $PATH
# /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# The shell searches left to right. First match wins.
Adding to PATH#
# Add a directory to the END of PATH
export PATH="$PATH:$HOME/bin"
# Add a directory to the BEGINNING of PATH (higher priority)
export PATH="$HOME/.local/bin:$PATH"
# Make it permanent — add to ~/.bashrc or ~/.profile
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
Where Commands Live#
which python3 # show which python3 will run
type ls # show if ls is alias, function, or binary
command -v git # check if git exists in PATH
Aliases#
An alias is a shortcut for a command:
# Define an alias
alias ll='ls -alF'
alias la='ls -A'
alias update='sudo apt update && sudo apt upgrade -y'
alias gs='git status'
alias ..='cd ..'
alias ...='cd ../..'
alias grep='grep --color=auto'
# View all aliases
alias
# Remove an alias (current session only)
unalias ll
# Run the original command (bypass alias)
\ls # backslash bypasses the alias
command ls # also bypasses aliases
Make aliases permanent by adding them to ~/.bashrc:
# ~/.bashrc
alias ll='ls -alF'
alias update='sudo apt update && sudo apt upgrade -y'
Tip: Some users keep aliases in a separate file
~/.bash_aliases. Ubuntu’s default.bashrcalready sources this file if it exists.
Shell Functions#
Functions are more powerful than aliases — they accept arguments and can contain logic:
# Define a function
mkcd() {
mkdir -p "$1" && cd "$1"
}
# Use it
mkcd my-new-project # creates dir and cd's into it
# More examples
extract() {
case "$1" in
*.tar.gz) tar xzf "$1" ;;
*.tar.bz2) tar xjf "$1" ;;
*.tar.xz) tar xJf "$1" ;;
*.zip) unzip "$1" ;;
*.gz) gunzip "$1" ;;
*) echo "Unknown format: $1" ;;
esac
}
# Find and cd into a directory
fcd() {
local dir
dir=$(find . -type d -name "$1" 2>/dev/null | head -1)
if [ -n "$dir" ]; then
cd "$dir"
else
echo "Directory '$1' not found"
fi
}
Add functions to ~/.bashrc to make them permanent.
Customizing the Prompt (PS1)#
The PS1 variable controls your command prompt. Special escape sequences:
| Escape | Meaning |
|---|---|
\u |
Username |
\h |
Hostname (short) |
\H |
Hostname (full) |
\w |
Current directory (full path, ~ for home) |
\W |
Current directory (basename only) |
\d |
Date |
\t |
Time (24h) |
\T |
Time (12h) |
\n |
Newline |
\$ |
$ for regular user, # for root |
\[...\] |
Non-printing characters (for colors — prevents line-wrapping issues) |
Examples#
# Simple
PS1='\u@\h:\w\$ '
# kmiguel@mypc:~/projects$
# Minimal
PS1='\W\$ '
# projects$
# With git branch (if git is installed)
PS1='\u@\h:\w$(__git_ps1 " (%s)")\$ '
# kmiguel@mypc:~/project (main)$
Adding Colors#
# Color codes (wrap in \[ and \] to prevent display issues)
# \[\e[COLORm\] — start color
# \[\e[0m\] — reset to default
# Common colors: 31=red, 32=green, 33=yellow, 34=blue, 35=magenta, 36=cyan
# Bold: add 1; before the color number
# Green user@host, blue directory
PS1='\[\e[1;32m\]\u@\h\[\e[0m\]:\[\e[1;34m\]\w\[\e[0m\]\$ '
Shell Options#
# Useful options to add to ~/.bashrc
# Append to history instead of overwriting
shopt -s histappend
# Resize terminal output on window resize
shopt -s checkwinsize
# cd into directories by typing just the name
shopt -s autocd
# Correct minor typos in cd
shopt -s cdspell
# Extended globbing (pattern matching)
shopt -s extglob
# History settings
HISTSIZE=10000 # lines in memory
HISTFILESIZE=20000 # lines in file
HISTCONTROL=ignoreboth # ignore duplicates and lines starting with space
Applying Changes#
After editing ~/.bashrc:
source ~/.bashrc
# or
. ~/.bashrc
Lab#
Exercise 1: Explore Your Startup Files#
# What shell are you running?
echo $SHELL
echo $0
# View your current .bashrc
cat ~/.bashrc
# Check if .profile sources .bashrc
grep -n bashrc ~/.profile
# View your PATH
echo $PATH | tr ':' '\n'
Exercise 2: Create Aliases#
# Add aliases to ~/.bashrc
cat >> ~/.bashrc << 'EOF'
# Custom aliases
alias ll='ls -alF'
alias la='ls -A'
alias ..='cd ..'
alias ...='cd ../..'
alias h='history | tail -20'
alias ports='ss -tlnp'
EOF
# Apply
source ~/.bashrc
# Test
ll
..
h
Exercise 3: Add a Function#
# Add to ~/.bashrc
cat >> ~/.bashrc << 'EOF'
# Create directory and cd into it
mkcd() {
mkdir -p "$1" && cd "$1"
}
EOF
source ~/.bashrc
# Test
mkcd /tmp/testdir
pwd
# /tmp/testdir
cd ~
rmdir /tmp/testdir
Exercise 4: Customize Your Prompt#
# Save current PS1
echo "Current PS1: $PS1"
# Try a colored prompt
PS1='\[\e[1;32m\]\u@\h\[\e[0m\]:\[\e[1;34m\]\w\[\e[0m\]\$ '
# If you like it, add to ~/.bashrc:
# (replace the existing PS1 line or add at the end)
Exercise 5: Manage PATH#
# Create a personal bin directory
mkdir -p ~/bin
# Add it to PATH in .bashrc
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# Create a simple script in it
cat > ~/bin/greet << 'EOF'
#!/bin/bash
echo "Hello, $USER! Today is $(date '+%A, %B %d')."
EOF
chmod +x ~/bin/greet
# Run it from anywhere
greet
Review#
1. What is the difference between ~/.bashrc and ~/.profile?
~/.bashrc runs for every interactive non-login shell (and is typically sourced by ~/.profile on Ubuntu/Debian). Put aliases, functions, and prompt customization here. ~/.profile runs only for login shells. Put environment variables (export) here.
2. What is the PATH variable?
A colon-separated list of directories the shell searches (left to right) when you type a command. The first matching executable found wins.
3. How do you make an alias permanent?
Add the alias line to ~/.bashrc (or ~/.bash_aliases on Ubuntu). Then run source ~/.bashrc to apply it in the current session.
4. How do you apply changes to .bashrc without logging out?
Run source ~/.bashrc (or . ~/.bashrc). This re-reads the file in the current shell.
5. What does PS1 control?
The primary command prompt. It supports escape sequences like \u (username), \h (hostname), \w (working directory), and color codes.
Previous: tmux | Next: find, locate, and xargs