Shell Scripting Guide (Bash)

Comprehensive reference for Bash shell scripting: variables, control flow, functions, error handling, debugging, and best practices.

  • JSON9,372 B
  • YAML6,250 B · −33%
  • TOON5,660 B · −40%

A guide to Bash scripting by topic with examples: variables and expansion, control flow, functions, error handling, file operations, arrays and maps, debugging and best practices.

Use it when

  • You are writing or reviewing a shell script.
  • You need a safe idiom for a common scripting task.

Watch out for

  • Bash-specific features (arrays, [[ ]]) are not available in POSIX sh; set the shebang accordingly.
  • Use set -euo pipefail and quote variables, and consider a different language for complex logic.

The data

Sections

TopicExamples
Variables and Expansion
NameCode
Simple assignmentname="John" echo "Hello, $name"
Command substitutioncurrent_dir=$(pwd) echo "We are in $current_dir"
Default valuesecho "${PORT:-8080}" # prints 8080 if PORT unset echo "${PORT:=8080}" # sets PORT to 8080 if unset echo "${PORT:?Error: PORT required}" # exits if unset
String manipulationstr="hello_world.txt" echo "${str%.*}" # hello_world (remove shortest suffix) echo "${str##*.}" # txt (remove longest prefix) echo "${str/_/-}" # hello-world.txt (replace first _)
Control Flow
NameCode
If statementif [ -f "$file" ]; then echo "File exists" elif [ -d "$file" ]; then echo "Is a directory" else echo "Not found" fi
For loopfor item in "${array[@]}"; do echo "Processing: $item" done # Or with range for i in {1..10}; do echo "Count: $i" done
While loopwhile IFS= read -r line; do echo "Line: $line" done < "input.txt"
Case statementcase "$1" in start) echo "Starting...";; stop) echo "Stopping...";; restart) echo "Restarting...";; *) echo "Usage: $0 {start|stop|restart}"; exit 1;; esac
Functions
NameCode
Define and callgreet() { local name="$1" echo "Hello, $name!" } greet "World" # Hello, World!
Return valuesis_even() { local num=$1 return $(( num % 2 )) } if is_even 42; then echo "Even" else echo "Odd" fi
Output captureget_date() { date "+%Y-%m-%d" } today=$(get_date) echo "Today is $today"
Error Handling
NameCode
Exit on errorset -e # Exit immediately on error set -u # Error on undefined variables set -o pipefail # Fail pipeline on first error # Combined set -euo pipefail
Trap signalscleanup() { echo "Cleaning up..." rm -f /tmp/tempfile exit } trap cleanup EXIT SIGINT SIGTERM
Check command successif ! command -v docker &> /dev/null; then echo "Docker is not installed" exit 1 fi
File Operations
NameCode
Read file line by linewhile IFS= read -r line; do echo "$line" done < "input.txt"
Check file conditionsif [ -f "$file" ]; then echo "regular file"; fi if [ -d "$dir" ]; then echo "directory"; fi if [ -x "$bin" ]; then echo "executable"; fi if [ -z "$str" ]; then echo "empty string"; fi if [ -n "$str" ]; then echo "non-empty"; fi
Temp filestempfile=$(mktemp) echo "Writing to $tempfile" # ... use it ... rm -f "$tempfile"
Arrays and Maps
NameCode
Indexed arrayfruits=("apple" "banana" "cherry") echo "${fruits[0]}" # apple echo "${#fruits[@]}" # length 3 echo "${fruits[@]}" # all elements
Associative array (Bash 4+)declare -A config config["host"]="localhost" config["port"]=8080 echo "${config[host]}" # localhost
Debugging
NameCode
Enable debug modeset -x # Print commands and their arguments as executed # ... debug code ... set +x # Disable debug # Or run script with: # bash -x script.sh
Check syntax without runningbash -n script.sh # Returns silently if syntax is valid
ShellCheck static analysis# Install: apt install shellcheck / brew install shellcheck # Run: shellcheck script.sh # Catches: unquoted variables, missing shebang, common pitfalls
Best Practices
NameCode
Script header#!/usr/bin/env bash set -euo pipefail IFS=$'\n\t'
Usage functionusage() { cat <<EOF Usage: $0 [options] -h Show help -v Verbose mode -f Input file EOF exit 1 } while getopts "hf:v" opt; do case $opt in h) usage;; f) file="$OPTARG";; v) verbose=true;; *) usage;; esac done
Portable scripting# Prefer POSIX sh -c over bashisms when portability matters # Use printf instead of echo for consistent behavior # Quote all variable expansions # Use $(...) over backticks

Fields

The shape of this dataset, read from the data itself: every column, its type and a real value. Agents can use this to plan a query without fetching the whole document.

SectionFieldTypeExample
sectionstopicstringVariables and Expansion
sectionsexamplesarray[4 items]

Fetch the same bytes

The static files contain the same reference rows as the API, with no API rate limit. Live metadata, such as view counts, may differ. Use the API for content negotiation; use the static files for a cacheable snapshot.

curl "https://yjtoon.yunusemrevurgun.com/api/dataset/shell-scripting-guide?format=toon"
const res = await fetch(
  "https://yjtoon.yunusemrevurgun.com/static-data/dataset/shell-scripting-guide.toon"
);
const toon = await res.text();

Rate limit: 120 requests per minute per IP, no key and no signup. API reference →

Topics

  • bash
  • shell
  • scripting
  • unix
  • linux
  • automation
  • devops

Search the library

Search by a topic, title, or keyword.

Start with a collection

Browse all 205 datasets