A practical Bash reference for writing shell scripts: variables, conditionals, loops, functions, string and array handling, and the safety settings every script should start with. Copy-paste ready.
#!/usr/bin/env bash
set -euo pipefail # exit on error, unset var, and failed pipe
IFS=$'\n\t' # safer word splitting| Flag | Effect |
|---|---|
set -e |
exit immediately if a command fails |
set -u |
error on undefined variables |
set -o pipefail |
a pipeline fails if any part fails |
set -x |
print each command (debug) |
name="Ada"
echo "$name" # always quote
greeting="Hello, $name"
count=$((3 + 4)) # arithmetic
today=$(date +%F) # command substitution
readonly PI=3.14 # constant
export PATH="$PATH:/opt/bin"| Var | Meaning |
|---|---|
$0 |
script name |
$1 $2 … |
positional arguments |
$# |
number of arguments |
$@ |
all arguments (as separate words) |
$* |
all arguments (as one string) |
$? |
exit code of last command |
$$ |
current PID |
$! |
PID of last background job |
"${1:-default}" # use default if $1 unset
"${VAR:?must be set}" # error out if unsetif [[ "$x" -gt 10 ]]; then
echo "big"
elif [[ "$x" -eq 10 ]]; then
echo "ten"
else
echo "small"
fi
# string tests
[[ -z "$s" ]] # empty
[[ -n "$s" ]] # not empty
[[ "$a" == "$b" ]]
[[ "$s" == *.txt ]] # glob match
[[ "$s" =~ ^[0-9]+$ ]] # regex match
# file tests
[[ -f file ]] # is a file
[[ -d dir ]] # is a directory
[[ -e path ]] # exists
[[ -x file ]] # executableNumeric operators: -eq -ne -lt -le -gt -ge
for i in 1 2 3; do echo "$i"; done
for f in *.txt; do echo "$f"; done
for i in {1..10}; do echo "$i"; done
for ((i=0; i<5; i++)); do echo "$i"; done
while read -r line; do
echo "$line"
done < file.txt
until [[ "$done" == "yes" ]]; do ...; donegreet() {
local name="$1" # local scope
echo "Hello, $name"
return 0
}
greet "Ada"
result=$(greet "Bob") # capture output${#str} # length
${str:0:3} # substring (offset, length)
${str/foo/bar} # replace first
${str//foo/bar} # replace all
${str^^} # uppercase
${str,,} # lowercase
${file%.txt} # strip suffix
${path##*/} # basename
${path%/*} # dirnamearr=(a b c)
echo "${arr[0]}" # first
echo "${arr[@]}" # all
echo "${#arr[@]}" # length
arr+=(d) # append
for x in "${arr[@]}"; do echo "$x"; done
declare -A map # associative array
map[name]="Ada"
echo "${map[name]}"command || echo "failed" # run on failure
command && echo "ok" # run on success
mkdir -p "$dir" # no error if exists
trap 'echo cleanup; rm -f "$tmp"' EXIT # cleanup on exit
[[ $# -eq 0 ]] && { echo "usage: $0 <arg>"; exit 1; }| Task | Snippet |
|---|---|
| Safe script header | set -euo pipefail |
| Default value | ${1:-default} |
| Loop over files | for f in *.txt; do …; done |
| Read file line by line | while read -r l; do …; done < f |
| String length | ${#s} |
| Replace all | ${s//a/b} |
| Basename | ${path##*/} |
| Regex test | [[ "$s" =~ ^[0-9]+$ ]] |
| Cleanup on exit | trap '…' EXIT |
Maintained by the team at EchoGlobal. Hiring infrastructure talent? See our curated lists of Top DevOps Engineers, Top TechOps Experts, and Top Docker Developers on GitHub, or hire pre-vetted engineers in days.