Shell, explained

What does << EOF mean? Here-documents explained

cat << EOF > config.txt

<< starts a here-document: the lines that follow, up to a line containing only the word you chose (EOF by habit), are given to the command as its input. cat << EOF > config.txt therefore writes those lines into config.txt. It is the standard way to put several lines of text into a script.

The lines up to EOF become the input

cat reads the two lines as if they came from a file and prints them; > sends that into config.txt. The closing EOF is not part of the text.

$

Tap a part of the command to find it below

<<here-documentINPUT
host=localhost
port=8080
EOF
$ cat

output → config.txt

>config.txtREPLACED
host=localhost
port=8080
Tap any part of the command to see what it does

Variables are filled in

With name=ana set, the shell replaces $name before cat sees the text, just as it would inside double quotes.

$

Tap a part of the command to find it below

<<here-documentINPUT
Hello $name
EOF
$ catOUTPUT
Hello ana
Tap any part of the command to see what it does

Quote the word to switch that off

With 'EOF' in quotes, the text is passed on exactly as written. Use this when the text is itself code, full of $ signs.

$

Tap a part of the command to find it below

<<here-documentINPUT
Hello $name
EOF
$ catOUTPUT
Hello $name
Tap any part of the command to see what it does

Part by part

cat
Prints whatever it reads on its input.
<<
Says: my input is not a file, it is the lines that follow.
EOF
The end marker. Any word works; EOF (“end of file”) is the convention.
> config.txt
An ordinary redirection: what cat prints goes into the file.
EOF
Alone on a line, with no spaces around it, it ends the text.

Common mistakes

Indenting the closing EOF

The end marker must start in the first column, with nothing after it. Indented by even one space it is treated as text, and the shell keeps reading to the end of the script.

Expecting <<- to strip spaces

<<- removes leading tabs from every line, so the text can be indented inside an if or a function. It removes tabs only: with spaces, the closing marker is not found.

Try it

$ cat << EOF Hello $USER EOF

Prints Hello and your user name.

$ cat << 'EOF' Hello $USER EOF

Prints Hello $USER, untouched.

$ wc -l << EOF a b c EOF

Any command that reads input works: prints 3.

Questions

Does the word have to be EOF?

No. Any word works, as long as the same one closes the text: END, SQL, HTML. Pick one that does not appear on a line of its own inside the text.

What is the difference between << and <<<?

<< takes several lines up to a marker. <<< is a here-string: it takes the one string that follows, as in grep o <<< "hello". <<< is a bash and zsh feature, not plain sh.

How do I write a file that needs sudo?

sudo cat << EOF > /etc/file fails, because the > is done by your own shell. Let tee write the file instead: sudo tee /etc/file << EOF.

Can I use a heredoc with ssh?

Yes: ssh server bash << 'EOF' runs the lines on the remote machine. Quote the marker so variables are expanded there and not on your machine first.

Terminaster

Stop looking up the same command twice.

Ask about any command you run into and see what it actually does. Terminaster then brings it back just before you would forget it, until you can type it without searching.

Terminaster's tutor answering “What does chmod 754 mean?” by taking the command apart: chmod, then 7 for you, 5 for your group, 4 for everyone else, and the file name