How To Use Heredocs Inside Your Bash Scripts

If you’ve ever used wget to download a config file, tested commands on Ubuntu 24.04.4, searched logs with locate, monitored processes with top, created directories with mkdir, or even executed scripts as the nobody user for security testing, you already know how powerful the Linux command line can be. But there’s one Bash feature that many users overlook — and once you start using it, your scripts become dramatically cleaner and more powerful: Heredoc.

In this in-depth guide, I’ll walk you through everything you need to know about using Heredoc inside Bash scripts. We’ll cover syntax, variable behavior, redirection, indentation tricks, security considerations, advanced patterns, and real-world examples.

This article is written from hands-on experience — the goal is not just to explain heredocs, but to help you actually use them confidently in production scripts.


What Is a Heredoc in Bash?

A Heredoc (short for Here Document) is a type of input redirection that allows you to pass multiple lines of text to a command directly inside your script.

Instead of writing long echo chains or creating temporary files, you can embed structured multi-line content directly inside your Bash script.

Basic syntax:

command <<DELIMITER
text
text
DELIMITER

Everything between <<DELIMITER and the closing DELIMITER is passed to the command’s standard input.


Why Use Heredoc?

Here’s why I personally prefer heredocs over multiple echo statements:

  • Cleaner and easier to read
  • Ideal for configuration files
  • Great for SQL queries
  • Perfect for multi-line messages
  • Easier automation scripting
  • Useful in SSH remote execution
  • Supports variable expansion (when needed)
  • Can disable expansion for literal output

If you’re writing scripts that generate files or execute remote commands, heredocs are essential.


Basic Heredoc Example

Let’s start with something simple — printing multi-line text:

cat <<EOF
Hello,
This is a heredoc example.
It allows multiple lines.
EOF

Output:

Hello,
This is a heredoc example.
It allows multiple lines.

cat receives everything between the two EOF markers.

You can replace EOF with any word you like:

cat <<MYTEXT
Custom delimiter example
MYTEXT

The delimiter just has to match at the beginning and end.


Writing to a File Using Heredoc

One of the most common use cases: generating configuration files.

cat <<EOF > config.txt
username=admin
password=secret
port=8080
EOF

This will create (or overwrite) config.txt.

To append instead:

cat <<EOF >> config.txt
new_setting=true
EOF

This is much cleaner than using multiple echo commands.


Using Variables Inside Heredoc

By default, variables are expanded.

name="IdoLinux"

cat <<EOF
Welcome to $name
Today is $(date)
EOF

Output includes the variable values.

This makes heredocs powerful for dynamic file generation.


Preventing Variable Expansion

Sometimes you need to output literal text — like $PATH or $(command).

To prevent expansion, quote the delimiter:

cat <<'EOF'
The variable $USER will not expand.
Command substitution $(date) will not run.
EOF

Using single quotes around the delimiter disables:

  • Variable expansion
  • Command substitution
  • Arithmetic expansion

This is critical when generating scripts or config templates.


Indented Heredoc with <<-

If you want your script to stay visually clean, use:

cat <<-EOF
    This line is indented with tabs.
    Bash removes leading tabs.
EOF

Important note:

  • Only tabs are stripped
  • Spaces will not be removed

This helps maintain script readability.


Using Heredoc with sudo or Another User

A common mistake is:

sudo cat <<EOF > /etc/file.conf
...
EOF

This fails because redirection happens before sudo.

Correct approach:

sudo tee /etc/file.conf > /dev/null <<EOF
secure_config=true
EOF

Or:

sudo bash -c 'cat <<EOF > /etc/file.conf
secure_config=true
EOF'

If you’re testing as the nobody user:

sudo -u nobody bash <<EOF
whoami
EOF

This executes the heredoc as another user safely.


Using Heredoc with SSH

This is one of my favorite uses:

ssh user@server <<EOF
mkdir /tmp/testdir
echo "Hello from remote server" > /tmp/testdir/file.txt
EOF

The commands inside the heredoc execute remotely.

If variables should expand locally:

VAR="LocalValue"

ssh user@server <<EOF
echo $VAR
EOF

If variables should expand remotely:

ssh user@server <<'EOF'
echo $HOSTNAME
EOF

The difference matters.


Passing Variables into a Heredoc Safely

Sometimes you want selective expansion.

Example:

name="Server1"

cat <<EOF
server_name=$name
literal_dollar=\$HOME
EOF

Or escape specific characters using backslashes:

cat <<EOF
This is \$PATH
EOF

You control expansion carefully depending on use case.


Heredoc with SQL Queries

Very common in admin scripts:

mysql -u root -p <<EOF
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE users (id INT, name VARCHAR(50));
EOF

This avoids external SQL files.


Generating Scripts with Heredoc

You can even create another script:

cat <<EOF > deploy.sh
#!/bin/bash
echo "Deployment started"
date
EOF

chmod +x deploy.sh

This is often used in automation environments.


Heredoc vs Here String

Don’t confuse heredocs with Here Strings.

Heredoc:

command <<EOF
multiple lines
EOF

Here string:

command <<< "single line input"

Heredoc = multi-line
Here string = single line


Common Errors and Debugging Tips

1. Delimiter Not Matching

The closing delimiter must:

  • Be alone on the line
  • Have no trailing spaces
  • Match exactly

Wrong:

EOF 

Correct:

EOF

2. Unexpected Variable Expansion

If you see unintended variable values:

  • Quote the delimiter
  • Escape $ with \

3. Indentation Not Working

Remember:

<<-EOF removes tabs, not spaces.


Security Considerations

Be careful when injecting variables into heredocs, especially if input comes from users.

Bad practice:

cat <<EOF > file.txt
$username
EOF

If $username comes from untrusted input, validate or sanitize it first.

Also, when writing into system directories like /etc, always verify permissions and use sudo tee if needed.


Advanced Pattern: Combining Heredoc with Functions

You can embed heredocs inside functions:

generate_config() {
    cat <<EOF
app_name=$1
env=production
EOF
}

generate_config "MyApp"

Clean and reusable.


When Should You Use Heredoc?

Use heredocs when:

  • Generating config files
  • Running remote SSH blocks
  • Passing SQL commands
  • Writing automation scripts
  • Creating large multi-line outputs
  • Producing formatted CLI messages
  • Bootstrapping environments

Avoid when:

  • Only one line is needed (use here-string)
  • Content is extremely large (use template file instead)

Practical Real-World Example

Here’s a small real automation scenario:

#!/bin/bash

PROJECT="demo_app"

mkdir -p /tmp/$PROJECT

cat <<EOF > /tmp/$PROJECT/README.md
# $PROJECT

Created on $(date)

This directory was automatically generated.
EOF

echo "Project structure created successfully."

Clean, readable, and self-contained.


Final Thoughts

Heredocs are one of those Bash features that feel optional — until you start using them properly. Then you wonder how you ever wrote clean automation scripts without them.

They make:

  • Config generation easier
  • Remote execution clearer
  • Scripts more readable
  • Multi-line handling elegant
  • Automation more professional

If you’re serious about writing maintainable Bash scripts on modern Linux systems (including Ubuntu 24.04.4 and beyond), mastering heredocs is not optional — it’s essential.

Start small. Replace your next block of repeated echo commands with a heredoc. You’ll immediately notice the difference.

Happy scripting.

3 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *