This lesson covers the shell skills used every day: how commands are built, how quoting changes meaning, how PATH finds programs, and how to get help quickly. Examples assume the Bash shell.
A shell is a program that reads what a user types and runs it. Bash is the default shell on many systems. Check the current shell with echo $SHELL
.
Prerequisites
- A Linux system from Day 1 in a VM, in WSL, or on bare metal
- Access to a terminal window
- Ability to update packages with
sudo apt update
on Ubuntu orsudo dnf upgrade
on Fedora
Anatomy of a command
Commands usually have four parts.
program -s --long argument1 argument2
program
: the tool to run, for examplels
orcat
- options: short options start with a single dash, long options start with two dashes
- arguments: items the program works on, such as files or directories
Examples:
ls -la # list files with details, show hidden files
mkdir projects && cd projects
cp /etc/hosts ./hosts.backup
When a file name begins with a dash, stop option parsing with --
to avoid surprises, for example rm -- -weird-name
or grep -- "-pattern" file.txt
.
Built-in and external commands
Some commands are Bash built-ins. Others are external programs stored on disk. Use type
or command -V
to check.
type cd # builtin
command -V ls # usually /usr/bin/ls
which ls # path of an external program
Built-ins provide help with help <name>
.
help cd
help alias
External programs provide manuals and inline help.
man ls
ls --help | less
Quoting rules that matter
Quoting changes how Bash parses text.
- Unquoted text allows globbing and word splitting; spaces break words; wildcards expand
- Single quotes
'...'
keep text exact; nothing inside changes - Double quotes
"..."
allow variable expansion and command substitution while protecting spaces - Backslash
\
escapes the next character only
Examples:
# unquoted: splits on spaces and expands globs
printf %s\n *
# single quotes: literal text
printf '%s\n' *
# double quotes: expands variables but keeps spaces
name="Majd Banat"
echo "Hello $name"
# escape one character
echo A\ B
Quote variables by default: "$var"
. This avoids bugs when values contain spaces or newlines.
Command substitution
Use $(...)
to insert the output of one command into another.
# show kernel version inside a sentence
echo "Kernel: $(uname -r)"
# save the current date in a variable
now=$(date +%F)
echo "Today is $now"
# nested example
echo "User $(id -un) on host $(hostname)"
Avoid backticks `...`
because they are hard to nest and read.
Globbing and expansions
Bash expands patterns before running the program.
# wildcards
ls *.log
ls file?.txt
# character classes
ls report_[AB].pdf
# brace expansion creates many words quickly
mkdir -p logs/{nginx,app,db}
cp -v config.{example,backup}
# tilde expansion to the home directory
cd ~
To search for a literal asterisk or question mark, quote the pattern.
grep "*.log" notes.txt
Never run rm -rf *
without confirming the current directory. Check with pwd
, then run ls
first to preview what will be removed. Add -i
for interactive prompts when unsure.
PATH and how Bash finds programs
When a program name is typed, Bash searches the directories in the PATH
variable from left to right.
echo $PATH | tr ':' '\n'
Create a personal ~/bin
directory and add it to the front of PATH so custom tools take priority.
mkdir -p "$HOME/bin"
# add once to the end of ~/.bashrc
printf '
# add personal bin to PATH
export PATH="$HOME/bin:$PATH"
' >> "$HOME/.bashrc"
# reload the current shell
source ~/.bashrc
Create a small script and run it from anywhere.
cat > "$HOME/bin/hi" <<'EOF'
#!/usr/bin/env bash
echo "Hi from $(hostname)"
EOF
chmod +x "$HOME/bin/hi"
hi
Some systems load ~/.profile
for login shells and ~/.bashrc
for interactive shells. If PATH changes do not persist after login, add the same export to both files.
Variables and environment
Set a shell variable with name=value
. Export it when child processes should see it.
color=blue
export color
# or in one line
export color=blue
printenv | grep -i color || true
Persistent settings belong in ~/.bashrc
so they load in new terminals.
printf '
# custom color for demo
export COLOR_PREFERENCE="blue"
' >> ~/.bashrc
source ~/.bashrc
Do not write name = value
. Bash will treat it as a command with three arguments. Use name=value
with no spaces.
Aliases and small functions
Aliases shorten common commands and small functions automate simple tasks. Keep them in ~/.bashrc
.
cat >> ~/.bashrc <<'EOF'
# helpful aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
# function with one argument
mkcd() { mkdir -p "$1" && cd "$1"; }
EOF
source ~/.bashrc
Test them.
ll
mkcd ~/playground/day2
pwd
Bypass an alias with a leading backslash.
\ls -1
History and faster editing
History and completion speed up work.
- Up and Down: browse previous commands
- Ctrl R: search history; type a few letters and press Enter to run the match
- Tab: complete commands and paths; press Tab twice to see choices
Add timestamps to history entries.
printf '
HISTTIMEFORMAT="%F %T "
' >> ~/.bashrc
source ~/.bashrc
history | tail -5
sudo !!
repeats the previous command with sudo. Useful after a permission denied error.
If a program hangs, press Ctrl C to send SIGINT. If it still hangs, close the terminal or use kill
from another terminal. Process control is covered later in the series.
Redirection and pipes
Input and output redirection and pipes are core building blocks.
# send output to a file (overwrite or append)
ls -la > listing.txt
ls -la >> listing.txt
# read input from a file
wc -l < listing.txt
# pipe output of one command into another
ps aux | grep ssh | grep -v grep
Chain commands with &&
when the second should run only if the first succeeds. Use ;
to run commands regardless of success.
mkdir -p ~/playground/day2 && cd ~/playground/day2
curl -s https://example.com | wc -c
Common mistakes and quick fixes
- Quote variables: prefer
"$var"
- Avoid editing system files as root unless required; prefer
sudo
for single commands - Check the source of a command with
type -a <name>
to see aliases and paths - Read error messages; Bash often explains what went wrong
- Use
--
to stop option parsing when a file name starts with a dash
Up next: Day 3 - Navigating the Filesystem and FHS
Day 3 focuses on the filesystem and the Linux directory layout. Learn fast navigation techniques and safe delete habits.