C.W.K.
Stream
Lesson 11 of 12 · published

Heredocs and Script Arguments

~10 min · heredoc, args, getopts

Level 0Window Tourist
0 XP0/95 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

Heredocs — embedded multi-line strings

cat <<EOF
Hello, $USER
Today is $(date +%Y-%m-%d)
EOF

Anything 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
EOF

Quoting 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.

Code

Heredoc + getopts in one script·bash
#!/usr/bin/env bash
set -euo pipefail
name=World
while getopts ':n:' opt; do
  case "$opt" in
    n) name=$OPTARG ;;
    *) echo "usage: $0 [-n NAME]" >&2; exit 2 ;;
  esac
done
cat <<EOF
Hello, $name!
from $0
EOF

External links

Exercise

Write greet.sh that takes -n NAME (default World) and prints a two-line greeting via heredoc. Test with ./greet.sh, ./greet.sh -n Pippa, ./greet.sh -x (should error).

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.