Skip to content
Here-Documents
step 1/5

Reading — step 1 of 5

Read

~2 min readTokenizing & Parsing

Here-Documents (<<EOF)

A here-document lets you embed a multi-line literal as a command's stdin, right inside your shell script. It's the cleanest way to pass a fixed payload (a SQL query, a config, an email body) to a tool like cat, psql, or curl --data-binary @-.

Three flavors

cat <<END               # 1. variables expand inside the body
hello $USER
END

cat <<'END'             # 2. quoted terminator -> NO expansion (literal)
hello $USER
END

cat <<-END              # 3. -EOF strips LEADING TABS from each body line
	hello
	world
END

Bash treats << differently from <: the body up to the closing terminator is collected by the parser, then written into a pipe (or temp file) whose read end becomes the child's stdin.

How the shell implements it

  1. Parse phase — when the parser sees <<WORD, it remembers WORD and starts buffering subsequent lines as the heredoc body.
  2. Terminator — collection ends when a line consists exactly of WORD (no leading/trailing whitespace, unless <<- is used, in which case leading tabs are stripped from the terminator line too).
  3. Expansion — if WORD was quoted ('EOF' or "EOF" or \EOF), the body is preserved literally. Otherwise $VAR and $(cmd) are expanded — but \n and other backslash escapes stay literal, since a heredoc body does not process them.
  4. Execution phase — bash pipe(2)s, writes the body into the write end, and dup2(read_fd, 0) in the child before exec.

Why you care

  • Embedded scripts (ssh host <<'EOF' ... EOF) are how every Ansible / Capistrano-era deploy script gets work done remotely.
  • The quoted-vs-unquoted distinction is the #1 source of subtle bugs: cat <<EOF\n$PATH\nEOF prints your PATH, not the literal string $PATH.
  • <<-EOF exists exactly so you can indent the body to match surrounding code without those indent tabs ending up in the output.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…