The command line (also known as shell, terminal, or CLI) is a text-based interface where users interact with their operating system by typing commands. Originating from Unix in the 1970s, it remains the most efficient way to automate tasks, manage systems, and perform complex operations that would be cumbersome with graphical interfaces. While graphical UIs are intuitive for beginners, the command line offers unmatched power through composability β the ability to chain simple commands into sophisticated workflows using pipes and redirection. Mastering command line fundamentals means understanding not just individual commands, but how they communicate through streams (stdin, stdout, stderr), enabling you to build pipelines where each tool does one thing well and passes its output to the next.
26 tables, 239 concepts. Select a concept node to jump to its table row.
Table 1: Directory Navigation
Navigating the filesystem fluently is the first skill any CLI user must internalize. pwd, cd, and ls form the absolute core; pushd/popd add a directory stack so you can jump between multiple locations without retyping paths β essential in long sessions involving many directories.
| Command | Example | Description |
|---|---|---|
cd /var/log | β’ Change directory β’ ~ = home, - = previous dir, .. = parent | |
ls -lah | β’ List directory contents β’ -l long format, -a hidden files, -h human-readable sizes | |
pwd | Print absolute path of current working directory | |
pushd /var/log | β’ Change to directory and push it onto the directory stack β’ returns to it with popd | |
popd | Remove top entry from directory stack and cd to the new top | |
dirs -v | β’ Display the directory stack β’ -v shows index numbers | |
tree -L 2 | β’ Display directory structure as visual tree β’ -L limits depth |
Table 2: File Operations
These commands create, copy, move, rename, delete, and inspect files β the basic CRUD of the filesystem. The -r flag (recursive), -i (interactive confirmation), and -p (preserve attributes or create parents) recur throughout; understanding them reduces the need to memorise each command separately.
| Command | Example | Description |
|---|---|---|
cp -r src/ dest/ | β’ Copy files/directories β’ -r recursive, -i interactive, -a preserve attributes | |
mv old.txt new.txt | β’ Move or rename files β’ same command serves both purposes | |
rm -rf dir/ | β’ Remove files/directories β’ -r recursive, -f force without confirmation | |
mkdir -p path/to/dir | β’ Make directory β’ -p creates all missing parent directories | |
touch file.txt | Create empty file or update timestamp of existing file | |
ln -s target link | β’ Create link β’ -s for symbolic (soft) link, omit -s for hard link | |
diff file1 file2 | β’ Show line-by-line differences between two files β’ -u for unified (patch-friendly) format | |
stat file.txt | Display detailed file metadata: size, inode, permissions, timestamps | |
tmp=$(mktemp) | β’ Create a unique temporary file safely β’ avoids race conditions vs manual naming | |
file archive.bin | Determine file type by content inspection (not extension) | |
rmdir emptydir | β’ Remove empty directory only β’ fails if any files exist inside |
Table 3: Viewing File Contents
Quickly reading files without opening an editor is one of the most frequent CLI tasks. cat dumps everything at once; less provides a scrollable pager; head/tail show the edges β choose based on file size and which part you need.
| Command | Example | Description |
|---|---|---|
cat file.txt | β’ Concatenate and display entire file β’ also joins multiple files to stdout | |
less file.txt | β’ Scrollable pager β’ q quit, / search, G end, g start β the preferred viewer for large files | |
head -n 20 file.txt | β’ Display first N lines β’ default 10 | |
tail -f /var/log/syslog | β’ Display last N lines β’ -f follows the file in real-time β essential for log monitoring | |
tac file.txt | β’ Print file in reverse line order ( cat backwards)β’ useful for processing log files newest-first | |
nl file.txt | β’ Print file with line numbers prepended β’ -b a numbers all lines including blank ones | |
more file.txt | β’ Forward-only pager β’ prefer less β more featureful and supports backward scrolling |
Table 4: Wildcards and Globbing
Shell globbing lets the shell expand patterns to matching filenames before the command even runs β it is the shell, not the command, doing the matching. This distinction explains why ls *.txt and ls '*.txt' behave completely differently.
| Pattern | Example | Description |
|---|---|---|
ls *.txt | β’ Matches any characters (including zero) β’ most common wildcard | |
ls file?.txt | Matches exactly one arbitrary character | |
ls [abc]*.txt | Matches any single character listed in the set | |
ls [0-9]*.log | Matches any single character in the range | |
ls [!a]*.txt | Matches any character not in the set (negation) | |
cp file.{txt,bak} | β’ Brace expansion β generates multiple strings β’ not strictly globbing but shell-expanded | |
ls **/*.txt | β’ Matches files recursively in all subdirectories β’ requires shopt -s globstar (Bash 4.0+) |
Table 5: Redirection Operators
Every Linux command has three standard streams: stdin (0), stdout (1), and stderr (2). Redirection operators route these streams to files, other commands, or each other β mastering them turns output into data you can store, compare, and feed back into pipelines.
| Operator | Example | Description |
|---|---|---|
cmd > file.txt | β’ Redirect stdout to file β’ overwrites existing content | |
cmd >> file.txt | β’ Redirect stdout to file β’ appends without overwriting | |
cmd < input.txt | Redirect file contents as stdin to command | |
cmd 2> error.log | Redirect stderr (file descriptor 2) to file | |
cmd > all.log 2>&1 | β’ Redirect stderr to same destination as stdout β’ order matters β > must come first | |
cmd &> all.log | Shorthand: redirect both stdout and stderr to file (Bash 4+) | |
cmd <<< "text" | Here-string β pass a single string as stdin without a file | |
cmd <<EOF textEOF | Here-document β pass multi-line text as stdin until the delimiter | |
cmd > /dev/null 2>&1 | β’ Discard all output β’ /dev/null silently swallows anything written to it |
Table 6: Pipes and Command Chaining
Pipes connect the stdout of one command to the stdin of the next, enabling the Unix philosophy of composing small tools into powerful workflows. The logical operators (&&, ||, ;) control whether subsequent commands run based on exit status β this is how scripts implement error-aware flows.
| Operator | Example | Description |
|---|---|---|
cmd1 | cmd2 | Pipe β connects stdout of cmd1 to stdin of cmd2 | |
cmd1 && cmd2 | Logical AND β cmd2 runs only if cmd1 exits 0 (success) | |
cmd1 || cmd2 | Logical OR β cmd2 runs only if cmd1 exits non-zero (failure) | |
cmd1 ; cmd2 | β’ Run commands sequentially β’ cmd2 runs regardless of cmd1's exit status | |
cmd | tee file.txt | Split output to both a file and stdout, continuing the pipeline | |
cmd & | β’ Run command in background β’ shell returns immediately | |
cmd1 |& cmd2 | Pipe both stdout and stderr of cmd1 to stdin of cmd2 (Bash 4+) |
Table 7: Text Processing
These stream-editing tools are the heart of shell text manipulation. Each does one thing: grep filters lines, sed transforms them, awk processes structured fields, sort/uniq deduplicate. Chaining them with pipes builds data-processing pipelines that rival dedicated ETL tools.
| Command | Example | Description |
|---|---|---|
grep -r "error" . | β’ Search text using patterns β’ -i case-insensitive, -v invert match, -r recursive, -n show line numbers | |
sed 's/old/new/g' file | β’ Stream editor β’ s/old/new/g substitutes all occurrences per lineβ’ -i edits file in-place | |
awk '{print $1}' file | β’ Pattern scanning and field processing β’ $1, $2 are field numbers, $NF is last field | |
sort -n -k2 file.txt | β’ Sort lines β’ -n numeric, -r reverse, -k by column, -u unique | |
sort file | uniq -c | β’ Remove adjacent duplicates (must sort first) β’ -c counts occurrences | |
cut -d: -f1 /etc/passwd | β’ Extract columns from text β’ -d sets delimiter, -f selects fields | |
tr 'a-z' 'A-Z' | β’ Translate or delete characters β’ converts lowercase to uppercase in this example | |
wc -l file.txt | Count lines ( -l), words (-w), or bytes (-c) | |
paste file1 file2 | β’ Merge lines from multiple files side by side (column-wise) β’ -d sets delimiter | |
join file1 file2 | Join lines on a common field (like a SQL inner join on sorted files) | |
comm -12 <(sort f1) <(sort f2) | β’ Compare two sorted files β’ -1 suppress unique-to-f1, -2 unique-to-f2, -3 suppress common |
Table 8: File Searching
Finding files by name, content, size, type, or age is a daily task. find is the most powerful and flexible tool β combine it with -exec or xargs to act on results. type is the most reliable way to discover which version of a command the shell will actually run.
| Command | Example | Description |
|---|---|---|
find . -name "*.log" -mtime -7 | β’ Search by name, type, size, time β’ -exec cmd {} \• runs command on each match | |
grep -r "TODO" . --include="*.py" | β’ Search file contents recursively β’ use --include to restrict to file types | |
find . -name "*.tmp" | xargs rm | β’ Build and execute commands from stdin β’ passes results as arguments in batches | |
locate filename | β’ Fast search using pre-built database β’ run updatedb to refreshβ’ less flexible than find | |
type -a python | Show all matches in PATH plus whether it is a builtin, function, or alias β more thorough than which | |
which python | β’ Show first executable found in PATH β’ only finds external commands | |
whereis bash | Locate binary, source, and manual page for a command |
Table 9: File Permissions
Every file has an owner, a group, and permission bits for owner, group, and others (read=4, write=2, execute=1). Understanding chmod notation (both octal and symbolic), umask, and chown is essential for both security and scripting. Run ls -l to see the resulting permission string.
| Command | Example | Description |
|---|---|---|
chmod 755 script.sh | β’ Change file mode (permissions) β’ octal ( 755) or symbolic (u+x, go-w) notation | |
chown user:group file | β’ Change file owner and group β’ -R applies recursively | |
chgrp staff file.txt | Change file group ownership only | |
umask 022 | β’ Set default permissions mask for newly created files β’ subtracts from 666 (files) / 777 (dirs) |
Table 10: Process Management
Understanding how processes start, stop, pause, and run in the background is essential for system administration and scripting. Job control (bg, fg, jobs) manages processes within your terminal session; nice/renice control CPU priority; nohup detaches processes from the terminal so they survive disconnect.
| Command | Example | Description |
|---|---|---|
ps aux | β’ List running processes β’ a all users, u user-oriented, x include non-terminal | |
kill -9 1234 | β’ Send signal to process by PID β’ -15 SIGTERM (graceful), -9 SIGKILL (force, cannot be caught) | |
top | β’ Display real-time system processes β’ q quit, k kill, r renice | |
htop | Interactive process viewer β more user-friendly than top with colour and mouse support | |
jobs -l | List background/suspended jobs in current shell session | |
bg %1 | β’ Resume suspended job in background β’ %N refers to job number | |
fg %1 | Bring background job to foreground | |
(keyboard) | β’ Suspend current foreground process (SIGTSTP) β’ resume with bg or fg | |
nohup cmd & | β’ Run command immune to hangup β’ continues after terminal close β’ output goes to nohup.out | |
nice -n 10 cmd | β’ Start command with lower CPU priority (niceness 10) β’ range β20 (highest) to 19 (lowest) | |
renice -n 5 -p 1234 | Change CPU priority of a running process by PID | |
wait $pid | Wait for background process to finish and capture its exit status | |
timeout 30 cmd | β’ Run command with a time limit β’ exits 124 if the command times out | |
watch -n 2 df -h | β’ Execute a command periodically (default 2s) and display output β’ -n sets interval | |
pkill -u username | β’ Kill processes matching a pattern or user β’ more flexible than killall | |
killall firefox | Kill all processes matching the executable name |
Table 11: Environment Variables
Environment variables pass configuration into processes and scripts. export makes a variable available to child processes; source executes a script in the current shell so its variables and functions become part of your session. PATH is the most critical variable β it determines which commands the shell finds.
| Command | Example | Description |
|---|---|---|
export PATH="$PATH:/new/path" | β’ Set environment variable for child processes β’ without export, variable is local to shell | |
source ~/.bashrc | β’ Execute script in current shell (not a subshell) β’ aliases and variables persist after it finishes | |
alias ll='ls -lah' | β’ Create a command shortcut β’ put in ~/.bashrc to make permanent | |
unalias ll | β’ Remove an alias β’ unalias -a removes all aliases | |
env | Display all environment variables for the current process | |
printenv HOME | β’ Print specific variable value β’ exits non-zero if variable is not set | |
echo $PATH | Display variable value using parameter expansion | |
unset TEMP_VAR | Remove variable from the environment |
Table 12: Special Variables
Bash sets several automatic variables that capture process state after every command. $? after every command tells you whether it succeeded. $@ and $* both expand all positional parameters but behave differently under double-quotes β $@ preserves individual arguments, $* joins them with IFS.
| Variable | Example | Description |
|---|---|---|
echo $? | β’ Exit status of last command β’ 0 = success, non-zero = failure | |
echo $$ | Process ID (PID) of current shell | |
echo $! | PID of last background process | |
echo $0 | Name of the script or shell being executed | |
echo $1 | Positional parameters β command-line arguments passed to script | |
echo $# | Count of positional parameters | |
for arg in "$@" | All positional parameters as separate words (preserves argument boundaries under quotes) | |
echo "$*" | All positional parameters as single string joined by first char of IFS | |
echo $LINENO | β’ Current line number in the script β’ useful in error messages | |
echo $BASHPID | PID of the current Bash process (differs from $$ inside subshells) |
Table 13: Command Substitution and Expansion
Parameter expansion is one of the most powerful Bash features for manipulating strings, applying defaults, and extracting substrings β all without spawning a subprocess. Learning the full set of ${var...} forms eliminates many cases where people reach for sed or awk to do simple string work.
| Syntax | Example | Description |
|---|---|---|
now=$(date) | β’ Command substitution β executes cmd and returns its stdout β’ preferred over backticks | |
echo $((5 + 3)) | Arithmetic expansion β evaluates integer expression | |
echo ${name} | Parameter expansion β unambiguous variable reference | |
echo ${#str} | String length of variable | |
echo ${USER:-guest} | β’ Use default if variable is unset or null β’ does not set variable | |
${PORT:=8080} | β’ Assign default if variable is unset or null β’ also sets the variable | |
${FILE:?File required} | β’ Exit with error message if variable is unset or null β’ enforces required parameters | |
echo ${name:0:3} | β’ Substring extraction β’ offset is 0-based | |
echo ${path#*/} | Remove shortest match from beginning | |
echo ${path##*/} | Remove longest match from beginning (get filename from path) | |
echo ${file%.txt} | Remove shortest match from end (strip extension) | |
echo ${str/old/new} | Replace first occurrence of pattern | |
echo ${str//old/new} | Replace all occurrences of pattern | |
echo ${name^^} | Convert variable to uppercase (Bash 4.0+) | |
echo ${name,,} | Convert variable to lowercase (Bash 4.0+) | |
echo ${!prefix_name} | Indirect expansion β treat value of var as the name of another variable | |
now=`date` | β’ Old-style backtick command substitution β’ non-nestable β prefer $() (legacy) |
Table 14: Quoting and Escaping
Quoting determines which characters the shell interprets literally versus specially. Single quotes are the most aggressive: nothing inside expands. Double quotes allow variable and command substitution. Getting quoting wrong is the single most common source of subtle bugs in shell scripts β always quote variables unless you deliberately want word-splitting.
| Syntax | Example | Description |
|---|---|---|
echo 'Cost: $10' | β’ Single quotes β preserves literal value of all characters β’ no expansion of any kind | |
echo "User: $USER" | β’ Double quotes β allows variable expansion and command substitution β’ spaces preserved | |
echo \$USER | Backslash β escapes next character to literal value | |
echo $'line1\nline2' | ANSI-C quoting β interprets escape sequences like \n, \t, \a |
Table 15: Conditionals
Shell conditionals test file attributes, string values, and numeric relationships. Prefer [[ ... ]] over [ ... ] in Bash scripts β it avoids word-splitting pitfalls and supports pattern matching and &&/|| directly. The case statement is cleaner than chained elif when matching a single value against multiple patterns.
| Operator | Example | Description |
|---|---|---|
if [ -f file ]; then | β’ POSIX test using [ commandβ’ space required after [ and before ] | |
if [[ $a == $b ]]; then | β’ Bash extended test β’ supports pattern matching, &&, |β’ |β’ directly, no word-splitting | |
case "$1" in start) start_svc ;; stop) stop_svc ;; *) echo "unknown" ;;esac | β’ Match variable against multiple patterns β’ cleaner than nested elifβ’ * is the default catch-all | |
[ -f file.txt ] | True if path exists and is a regular file | |
[ -d /tmp ] | True if path exists and is a directory | |
[ -e path ] | True if path exists (any file type) | |
[ -x script.sh ] | True if file is readable / writable / executable by current user | |
[ -s file.txt ] | True if file exists and has non-zero size | |
[ -z "$var" ] | True if string length is zero (empty or unset) | |
[ -n "$var" ] | True if string length is non-zero | |
[[ $str == "text" ]] | β’ String comparison β’ == equality, != inequalityβ’ == supports glob patterns in [[ ]] | |
[ $a -eq 5 ] | β’ Numeric comparison inside [ ]β’ equal, not-equal, less-than, greater-than |
Table 16: Loops
Loops automate repetition. for iterates over a list or a C-style range; while runs until a condition is false; until is the inverse. The while IFS= read -r line pattern is the canonical way to process file lines safely β preserving whitespace and backslashes that naive loops would mangle.
| Loop | Example | Description |
|---|---|---|
for i in 1 2 3; do echo $idone | Iterate over list of items (words, filenames, or glob expansions) | |
for ((i=0; i<5; i++)); do echo $idone | C-style arithmetic for loop | |
while IFS= read -r line; do echo "$line"done < file.txt | β’ Safe line-by-line file processing β’ preserves leading spaces and backslashes | |
while [ $i -lt 10 ]; do ((i++))done | Loop while condition is true | |
until [ $i -ge 10 ]; do ((i++))done | Loop until condition becomes true (opposite of while) | |
select opt in start stop quit; do echo "Chose: $opt"done | β’ Generate an interactive numbered menu β’ reads user selection into REPLY | |
break | Exit loop immediately | |
continue | Skip to next iteration |
Table 17: Networking Commands
Network tools handle the full stack from raw connectivity checks (ping) through file transfer (curl, rsync, scp) to port inspection (ss, nc). The modern ip command has replaced ifconfig and route on most Linux distributions; ss has replaced netstat.
| Command | Example | Description |
|---|---|---|
curl -fsSL https://api.example.com | β’ Transfer data via HTTP, FTP, and many other protocols β’ -fsSL = fail silently, follow redirects | |
ssh user | β’ Secure remote login β’ -i key.pem specifies key, -L local port forwarding | |
rsync -av src/ dest/ | β’ Efficient sync β only transfers differences β’ -a archive (preserves attrs), -v verbose | |
scp file user:/path | Secure copy files over SSH | |
wget https://file.com/data.zip | β’ Download files from the web β’ supports recursive download and resuming | |
ping google.com | Test network connectivity with ICMP echo packets | |
ss -tuln | β’ Socket statistics β modern replacement for netstatβ’ -t TCP, -u UDP, -l listening, -n numeric | |
ip a | β’ Modern replacement for ifconfig/routeβ’ ip a show addresses, ip r show routes | |
nc -zv host 80 | β’ Netcat β raw TCP/UDP tool β’ -z port scan mode, also used to transfer files and test connectivity | |
dig example.com A | β’ DNS lookup tool β’ more detailed output than nslookupβ’ +short for concise results | |
traceroute google.com | Trace the network route (hops) to a host | |
netstat -tuln | β’ Network statistics β shows listening ports β’ prefer ss on modern systems (legacy) |
Table 18: Archiving and Compression
tar bundles files into archives; compression algorithms (gzip, bzip2, xz, zstd) shrink them. These are two separate concerns: tar flags -z, -j, -J, --zstd each invoke a different compressor. Cross-platform portability often dictates using zip.
| Command | Example | Description |
|---|---|---|
tar -czf archive.tar.gz dir/ | β’ Create/extract archives β’ -c create, -x extract, -z gzip, -j bzip2, -J xz, -f file | |
zip archive.zip files | β’ Create cross-platform ZIP archive β’ -r recursive | |
unzip archive.zip | β’ Extract ZIP archive β’ -l list contents without extracting | |
gzip file.txt | β’ Compress using gzip β’ creates file.txt.gz and removes original | |
gunzip file.txt.gz | Decompress gzip file | |
bzip2 file.txt | β’ Compress using bzip2 β’ better compression ratio than gzip, slower | |
xz file.txt | Compress using xz β best compression ratio of the common formats | |
zstd file.txt | β’ Compress using Zstandard β fast compression with ratio comparable to xz β’ widely used since 2023 |
Table 19: Command History and Shortcuts
Readline keyboard shortcuts and Bash history expansion dramatically reduce keystrokes. Ctrl+R reverse-incremental-search is the single most useful shortcut to memorise. History expansion (!!, !$, !:n) lets you reuse and modify previous commands without retyping.
| Shortcut | Example | Description |
|---|---|---|
(keyboard) | β’ Reverse search through command history β’ type to filter, Enter to run | |
sudo !! | Repeat last command β canonical use: sudo !! to re-run with elevated privileges | |
vim !$ | Last argument of the previous command | |
(keyboard) | Insert last argument of previous command (interactive equivalent of !$) | |
!42 | Execute command number n from history | |
!ssh | Execute most recent command starting with string | |
rm !* | All arguments from previous command | |
!:2 | Nth argument from previous command (0 = command itself) | |
(keyboard) | Move cursor to beginning of line | |
(keyboard) | Move cursor to end of line | |
(keyboard) | Delete from cursor to beginning of line | |
(keyboard) | Delete from cursor to end of line | |
(keyboard) | Delete word before cursor | |
(keyboard) | Clear screen (equivalent to clear) | |
history 20 | Display last N commands from command history |
Table 20: Subshells and Command Grouping
Parentheses create a subshell β commands run in an isolated copy of the environment, so directory changes and variable assignments don't leak back to the parent. Curly braces group commands in the current shell. Process substitution creates anonymous pipe endpoints that look like files, enabling powerful comparisons and multi-source reads.
| Syntax | Example | Description |
|---|---|---|
(cd /tmp; ls) | β’ Execute commands in subshell β’ directory/variable changes don't affect parent | |
{ echo "a"; echo "b"; } | β’ Group commands in current shell β’ trailing semicolon and spaces around braces required | |
diff <(ls /dir1) <(ls /dir2) | Input process substitution β treats command output as a readable file descriptor | |
cmd | tee >(gzip > out.gz) | Output process substitution β treats a command's stdin as a writable file descriptor |
Table 21: Arrays (Bash 4.0+)
Bash arrays store ordered (indexed) or key-value (associative) collections. mapfile / readarray is the canonical way to read command output or file lines into an indexed array β it avoids the pitfalls of parsing with a while loop and is faster for large inputs. Arrays do not survive export.
| Operation | Example | Description |
|---|---|---|
arr=(a b c) | β’ Create indexed array β’ elements accessed by numeric index starting at 0 | |
declare -A mapmap[key]=value | β’ Create key-value (hash) array β’ elements accessed by string key β’ requires declare -A | |
echo ${arr[0]} | Access element at index i | |
echo "${arr[@]}" | Expand all elements as separate words (preserves spaces in elements) | |
echo ${#arr[@]} | Get array length (number of elements) | |
arr+=(new) | Append element to end of array | |
echo "${arr[@]:1:3}" | Array slice β elements from index n, for m elements | |
unset arr[2] | β’ Delete element at index i (leaves gap β’ does not re-index) | |
mapfile -t lines < file.txt | β’ Read lines from stdin/file into indexed array ( -t strips trailing newlines)β’ also readarray |
Table 22: Input and Output Builtins
The read builtin reads a line from stdin and assigns words to variables β it is the standard way to accept user input and to safely iterate over file lines. printf formats output with far more precision and reliability than echo, especially when output must be consistent across different systems.
| Command | Example | Description |
|---|---|---|
read -r name | β’ Read line from stdin into variable β’ -r disables backslash interpretation β always use it | |
IFS= read -r line | β’ Read line preserving leading/trailing whitespace β’ canonical safe form for line processing | |
read -rp "Enter name: " name | β’ Display prompt and read input β’ combines prompt and read in one step | |
read -rsp "Password: " pass | β’ Read input in silent mode (no echo) β’ use for passwords | |
read -t 5 -r input | β’ Read with timeout in seconds β’ exits non-zero if timeout expires | |
read -ra words <<< "a b c" | β’ Read words into an array β’ each whitespace-separated token becomes an element | |
printf "%-20s %5d\n" "$name" $num | β’ Formatted output with C-style specifiers β’ %s string, %d integer, %f float, %x hex | |
printf -v result "%05d" 42 | β’ Store formatted output in variable instead of printing β’ avoids subshell overhead |
Table 23: Shell Script Safety Options
set options harden scripts against common failure modes that Bash otherwise silently ignores. Running with set -euo pipefail catches errors immediately, treats unset variables as errors, and propagates non-zero exit codes through pipelines β these three options together are the standard guard for production scripts.
| Option | Example | Description |
|---|---|---|
set -o errexit | β’ Exit immediately on any command failure β’ prevents cascading errors from being silently ignored | |
set -o nounset | β’ Treat unset variables as errors β’ catches typos in variable names | |
set -o pipefail | β’ Pipeline exit status is the last non-zero exit code β’ without it, cmd |• true always succeeds | |
set -o xtrace | β’ Print each command before executing it β’ invaluable for debugging scripts | |
set -euo pipefail | Combined idiom β the standard opening line for robust production scripts | |
shopt -s globstar | Enable ** to match files recursively across directories | |
shopt -s nullglob | β’ Unmatched glob patterns expand to empty string instead of literally β’ prevents [: *.txt: unexpected errors | |
shopt -s extglob | β’ Enable extended glob patterns like !(*.txt), +(a|• b), *(pattern) |
Table 24: Signal Handling
Signals are asynchronous notifications sent to a process by the OS or another process. The trap command intercepts them and runs a handler β most commonly used with EXIT to guarantee cleanup code runs regardless of how the script exits. SIGKILL (9) cannot be trapped or ignored; SIGTERM and SIGINT can.
| Command | Example | Description |
|---|---|---|
trap 'rm -f /tmp/lock' EXIT | β’ Run command when signal is received β’ EXIT fires on any exit (normal, error, or signal) | |
trap cleanup_fn EXIT SIGTERM | β’ Handle multiple signals with same handler β’ use a function for complex cleanup | |
trap - SIGINT | Reset signal to its default action | |
trap '' SIGINT | Ignore signal completely (empty string command) | |
trap -p SIGINT | β’ Display current traps β’ without argument shows all traps | |
kill -l | List all signal names and numbers on the system | |
kill -15 $pid | β’ Graceful shutdown signal β’ can be caught and handled β’ sent by kill with no flags | |
trap 'echo bye' SIGINT | β’ Keyboard interrupt β generated by Ctrl+C β’ can be caught | |
kill -9 $pid | β’ Force kill β cannot be caught, blocked, or ignored β’ use as last resort | |
trap reload SIGHUP | β’ Sent when terminal closes β’ traditionally used to tell daemons to reload config |
Table 25: Disk and System Monitoring
df shows free space at the filesystem level; du drills into directory and file sizes. Together they answer where disk space went. free, uname, and uptime give a quick system health snapshot without needing a full monitoring tool.
| Command | Example | Description |
|---|---|---|
df -h | β’ Show disk space usage of all mounted filesystems β’ -h human-readable, -T show filesystem type | |
du -sh /var/log | β’ Show disk usage of a directory (recursive total) β’ -s summary, -h human-readable | |
du -h --max-depth=1 / | β’ Show sizes of immediate subdirectories only β’ pipe to sort -hr to find largest | |
free -h | β’ Display memory usage (RAM + swap) β’ -h human-readable | |
uname -a | β’ Print system information β kernel version, hostname, architecture β’ -r just kernel release | |
uptime | Show how long the system has been running and load averages (1, 5, 15 min) | |
whoami | Print current username | |
id | Print user ID, group ID, and all group memberships for current user | |
hostname -f | β’ Print system hostname β’ -f fully-qualified domain name | |
date '+%Y-%m-%d %H:%M:%S' | Display or format the current date and time using strftime format strings | |
lsof -i :8080 | β’ List open files and network connections β’ -i :port shows what is using a port |
Table 26: Declaring and Typing Variables
declare (synonym: typeset) gives variables attributes that control their behavior: integer arithmetic, case conversion, export, and read-only status. Using local inside functions prevents variable leakage. readonly creates a constant that cannot be reassigned or unset.
| Command | Example | Description |
|---|---|---|
declare -i count=0 | β’ Declare variable as integer β’ arithmetic evaluated on assignment | |
declare -r PI=3.14 | β’ Declare read-only variable (constant) β’ cannot be reassigned or unset | |
readonly MAX_RETRIES=3 | β’ Mark variable as read-only β’ equivalent to declare -r | |
local tmp="value" | β’ Declare function-scoped variable β only valid inside the function β’ does not leak to global scope | |
declare -x PATH | β’ Export variable to child processes β’ equivalent to export | |
declare -u upper | Variable is auto-uppercased on assignment (Bash 4.0+) | |
declare -l lower | Variable is auto-lowercased on assignment (Bash 4.0+) | |
declare -p varname | Print variable attributes and value in a form that can be re-evaluated | |
declare -n ref=other_var | Create a nameref β variable acts as an alias to another variable (Bash 4.3+) |