Here Documents and Here Strings
Here documents (<<EOF) and here strings (<<<) let you pass multi-line text to commands without temp files. Essential for config generation, SQL, and long command inputs.
A here document (heredoc) is a way to provide multi-line input to a command directly in the script, without creating a temporary file. It's cleaner than multiple echo statements and essential for generating config files, running SQL queries, or producing formatted output.
Basic Heredoc — <<DELIMITER
# Feed multi-line text to a command
cat <<EOF
This is line 1
This is line 2
Variables ARE expanded: $USER
Command substitution works: $(date +%F)
EOF
# The delimiter can be any word — EOF is conventional, but not required
cat <<END
Hello from heredoc
ENDThe closing delimiter must be alone
The closing EOF (or whatever delimiter you chose) must be on its own line with no leading spaces or trailing characters. Even a trailing space makes Bash not recognize it as the end of the heredoc.
No Expansion — <<'EOF'
Quoting the delimiter with single quotes prevents all variable and command expansion — useful for writing scripts, Dockerfiles, awk programs, or anything that has its own $:
cat <<'EOF'
No expansion here: $USER $(date)
This goes into the file literally, including $PATH
Useful for writing other scripts or code
EOFIndented Heredoc — <<-
<<-EOF strips leading tabs (not spaces) from each line and the delimiter. This lets you indent the heredoc body to match the surrounding code.
function show_help {
cat <<-EOF
Usage: myscript [OPTIONS] <file>
Options:
-v Verbose output
-h Show this help
EOF
}
# Note: the body lines use TABs, not spaces, for indentationPractical Uses
#!/usr/bin/env bash
# 1. Generate a config file
cat > /etc/myapp/config.conf <<EOF
host=${DB_HOST:-localhost}
port=${DB_PORT:-5432}
name=${DB_NAME:-mydb}
generated=$(date)
EOF
# 2. Run SQL
psql "$DATABASE_URL" <<EOF
SELECT id, name, email
FROM users
WHERE active = true
ORDER BY created_at DESC
LIMIT 10;
EOF
# 3. Create a script file
cat > /usr/local/bin/cleanup <<'EOF'
#!/usr/bin/env bash
find /tmp -mtime +7 -delete
echo "Cleanup done"
EOF
chmod +x /usr/local/bin/cleanup
# 4. Feed to ssh (run remote commands)
ssh user@server <<EOF
cd /var/www/app
git pull
systemctl restart nginx
EOFHere String — <<<
# Feed a single string to stdin
grep "root" <<< "$(cat /etc/passwd)"
# Calculate with bc
result=$(bc <<< "scale=4; sqrt(144)")
echo "$result" # 12.0000
# Parse values with read
IFS=, read -r name age city <<< "Alice,30,NYC"
echo "Name: $name, Age: $age, City: $city"What does `cat <<'EOF'` do differently from `cat <<EOF`?
Write a script that generates a simple Nginx config file at /tmp/nginx-test.conf. Use a heredoc with variable expansion to fill in:
- A
server_namefrom variableDOMAIN(default: "example.com") - A
rootpath from variableWEBROOT(default: "/var/www/html")
Then print the file contents.