Heredocs — embedded multi-line strings
cat <<EOF
Hello, $USER
Today is $(date +%Y-%m-%d)
EOFAnything between the opening token (here EOF) and the closing one becomes stdin to the command. Variables and command substitutions expand by default.
Disable expansion: quote the delimiter
cat <<'EOF'
$USER stays literal
$(date) stays literal
EOFQuoting any character of the opening delimiter (typically the whole 'EOF') disables variable expansion. Use this for embedded config, scripts, or templates that contain shell-like syntax you don't want expanded.
Strip leading tabs: <<-
cat <<-EOF
hello
world
EOF<<- strips leading tabs (not spaces) from each line — handy for keeping heredocs indented inside if blocks.
Script arguments
$0— script name.$1 $2 ...— positional args.$#— number of args.$@— all args. Always quote:"$@".$*— args joined by IFS — usually wrong.shift— drop $1, renumber.
Parsing flags with getopts
verbose=0
while getopts ':vo:' opt; do
case "$opt" in
v) verbose=1 ;;
o) output="$OPTARG" ;;
\?) echo "bad flag: -$OPTARG" >&2; exit 2 ;;
esac
done
shift $((OPTIND - 1))POSIX getopts handles short flags only. For long flags, either parse them by hand or use bash's getopt variant or switch to Python's argparse. Most scripts get away with short-only.