#!/bin/bash → Shebang (always first line) chmod +x script.sh → Make executable ./script.sh → Run script bash script.sh → Run without executable bit bash -x script.sh → Debug mode (print each command) set -e → Exit on any error set -u → Exit on undefined variable set -o pipefail → Catch errors in pipes set -euo pipefail → Recommended: use all three
name="Alice" → Assign (no spaces around =)
echo
$0 → Script name
$1
read -p "Enter name: " name → Prompt and read input read -s -p "Password: " pass → Silent input (no echo) read -t 10 -p "Timeout in 10s: " val → Timeout read
if [ "$x" -eq 10 ]; then echo "ten" elif [ "$x" -gt 10 ]; then echo "greater" else echo "less" fi
if [[ "$name" == "Alice" ]]; then ... if [[ "$name" =~ ^Al ]]; then ... → Regex match
if [ -f file.txt ]; then ... → File exists if [ -d /path ]; then ... → Directory exists if [ -r file ]; then ... → File is readable if [ -z "$var" ]; then ... → Variable is empty if [ -n "$var" ]; then ... → Variable is not empty
- eq equal -ne not equal -lt less than -le less than or equal -gt greater than -ge greater than or equal
for i in 1 2 3; do echo $i; done for i in {1..10}; do echo $i; done for f in *.log; do echo "$f"; done for i in $(seq 1 5); do echo $i; done
for ((i=0; i<5; i++)); do echo $i; done
while [ $i -lt 10 ]; do ((i++)) done
while IFS= read -r line; do echo "$line" done < file.txt
until [ $i -ge 10 ]; do ((i++)); done
break → Exit loop continue → Skip to next iteration
greet() {
local name="$1" → local scopes variable to function
echo "Hello,
arr=("a" "b" "c") → Define array echo "${arr[0]}" → First element echo "${arr[@]}" → All elements echo "${#arr[@]}" → Length arr+=("d") → Append element for item in "${arr[@]}"; do ... → Loop array
declare -A map map["key"]="value" echo "${map["key"]}" for k in "${!map[@]}"; do echo "$k=${map[$k]}"; done
str="hello world" echo "${#str}" → Length echo "${str^^}" → Uppercase echo "${str,,}" → Lowercase echo "${str/hello/hi}" → Replace first echo "${str//l/L}" → Replace all echo "${str:0:5}" → Substring (start:length) echo "${str#hello }" → Strip prefix echo "${str%world}" → Strip suffix [[ "$str" == "world" ]] → Contains check
result=$((5 + 3)) → Integer arithmetic
((count++)) → Increment
((count--)) → Decrement
echo
echo "text" → Print with newline printf "%-10s %5d\n" "item" 42 → Formatted output command > file.txt → Redirect stdout (overwrite) command >> file.txt → Redirect stdout (append) command 2> error.log → Redirect stderr command 2>&1 → Merge stderr into stdout command &> file.txt → Redirect both stdout & stderr command | tee file.txt → Print AND write to file /dev/null → Discard output (black hole)
command || echo "failed" → Run if command fails command && echo "success" → Run if command succeeds command || exit 1 → Exit script on failure
trap 'echo "Error on line $LINENO"' ERR → Catch errors trap 'rm -f /tmp/tmpfile' EXIT → Cleanup on exit
if [[ $EUID -ne 0 ]]; then echo "Must run as root" && exit 1 fi
if [[ $# -lt 1 ]]; then echo "Usage: $0 " && exit 1 fi
ts=$(date +"%Y-%m-%d_%H-%M-%S")
tmpfile=$(mktemp /tmp/script.XXXXXX)
for i in {1..3}; do command && break || sleep 2 done
while getopts "n:v" opt; do case $opt in n) name="$OPTARG" ;; v) verbose=true ;; esac done
log() { echo "[$(date +%H:%M:%S)] $*"; } log "Script started"