Learn › Linux Foundations › Heredocs
<< - a hands-on Linux lab on a real virtual machine.
Feed a multi-line block of text straight into any command with the << heredoc: pick a delimiter word, close the block exactly, quote the delimiter to stop expansion, and send the block into files and filters. Practice in the sandbox, then on a real VM.
You want to hand a command three lines of text. A short note, a packing list, a block of settings. But the terminal has a habit you know well by now: the moment you press Enter, it runs whatever is on the line. Line one executes before line two exists.
There is a two-character operator that changes the deal. Type it, and bash stops running your lines and starts collecting them instead. It accepts line after line, patiently, until you type a closing word. You pick the word. This lesson is about that operator: <<, the heredoc.
The black boxes below are a practice terminal: a safe sandbox that only checks the one command each step teaches, so you cannot break anything. The shell here is bash, and every output you will see is real, captured from a live machine.
A heredoc (short for "here-document") feeds a block of lines to a command's standard input, stdin for short: the default place a command reads from when you do not name a file. You write << WORD after the command. Every line you type after that becomes input, until the shell reaches a line that is exactly WORD by itself.
That closing word is the delimiter, and it is never part of the input. The word is yours to choose. EOF (for "end of file") is the convention most engineers use, but END, DONE, or TEXT work identically.
Heredocs arrived with the Bourne shell in Unix Version 7, back in 1979, and every major shell since has kept them. The name means exactly what it says: the document is right here, in your session, instead of in a separate file.
The plainest heredoc feeds text to cat, the command that prints whatever it reads. Here is the whole session, typed line by line:
cat << EOF
Hello, world.
This is line two.
And line three.
EOF
The first line is the only command. When you press Enter after it, nothing runs. Instead bash prints >, its continuation prompt: a quiet signal that says "still collecting, keep typing." Each body line you type gets another >. The moment you type EOF alone, collecting stops and the command finally runs with the whole block as its input.
The practice box below grades that opening line. Type it, and the box replays the rest of the session for you: the > prompts, the body, the closing word, and the result, exactly as bash shows them. Before you run this, decide: will the word EOF appear in the printed output, or not?
prompt: student@linuxcamp:~$ answer: cat << EOF output: > Hello, world. > This is line two. > And line three. > EOF Hello, world. This is line two. And line three. hint: The command, then the heredoc operator, then the delimiter word: cat << EOF
Three lines in, three lines out, and EOF is nowhere in the output. The delimiter is a fence around your text, not part of it. Notice the > prompts too: that is bash collecting, not bash being broken. Remember that sight. It matters later in this lesson.
cat is just the demo dummy. A heredoc feeds stdin, so any command that reads stdin can sit in front of <<. Feed a block to wc -l (the line counter from the reading-files lessons) and it counts the body.
The session you are about to replay opens with wc -l << EOF, feeds three body lines, first, second, third, then closes with EOF. Before you run this, decide: will the count be 3 or 4? Three body lines went in, but the block took four lines to type, counting the one holding EOF.
prompt: student@linuxcamp:~$ answer: wc -l << EOF output: > first > second > third > EOF 3 hint: The counting command with its lines flag, then the operator and delimiter: wc -l << EOF
3. The delimiter line is not counted because it was never input; it is the fence. Now notice what you did not do in these two drills: you never created a file. Two commands received whole blocks of text and nothing landed on disk. That is the heredoc's whole job: multi-line input, straight from your fingers to a command's stdin.
Three rules govern the closing line, and all three exist so the shell can tell your text apart from the fence:
<< it must start at the left margin, no leading spaces or tabs.Here is a session mid-flight. Someone opened a block with the word END and typed two body lines. The shell is sitting at its > prompt, still collecting:
student@linuxcamp:~$ cat << END
> one
> two
Before you type, decide: which word ends this block, EOF or END? The box picks up the session at the > prompt. Type the one word that closes the block.
prompt: > answer: END output: one two hint: EOF is a convention, not a keyword. The only word that closes a heredoc is the word that opened it.
END closed it, the block ran, and cat printed the two lines. Typing EOF here would have added a third body line, because this block opened with END. Whatever word you open with is the only word that closes.
Near-misses do not close the block: end, End, and END with a leading space are all just body lines to the shell. It keeps collecting, silently. If a terminal ever seems to eat everything you type and shows > on every line, suspect an unclosed heredoc.
By default the body of a heredoc behaves like a double-quoted string: the shell expands it. A $name is replaced with the variable's value, and a $(...) runs as a command, before the text reaches stdin. Watch (this one is a read-through, no typing):
name=Ada
cat << EOF
User: $name
Home: is where the shell is
EOF
prints the first line already filled in:
User: Ada
Home: is where the shell is
Sometimes you want the opposite: the text kept literally, dollar signs and all. Think of a block that documents shell commands, or a script you are writing into a file. The off switch is small: quote the delimiter in the opening line, << 'EOF', and expansion is off for the whole body.
The session you are about to replay has name=Ada already set, opens with the quoted delimiter 'EOF', and feeds two booby-trapped lines: User: $name and Literal: $(echo hi). Before you run this, decide: will the first output line say User: Ada or User: $name?
prompt: student@linuxcamp:~$ answer: cat << 'EOF' ||| cat << "EOF" output: > User: $name > Literal: $(echo hi) > EOF User: $name Literal: $(echo hi) hint: Same opening line as always, but the delimiter wears quotes: cat << 'EOF'
User: $name, verbatim, and $(echo hi) never ran. Put this drill next to the read-through above and look at the one difference: the body did not change, only the delimiter grew a pair of quotes. One rule, two behaviors: a bare delimiter expands the body, a quoted delimiter keeps it literal. Note that the closing line stays plain EOF either way; only the opening word takes the quotes.
First: the body is fed exactly as you type it, indentation included. A body line that starts with a tab keeps the tab. That gets ugly inside indented scripts, and the fix, <<-, a heredoc variant that strips leading tabs, is the next lesson.
Second: a heredoc plays well with the redirection arrows you already know. cat << EOF > notes.txt collects a block and writes it into a file instead of the screen, a favorite trick for creating small config files on a server with no editor open. You will do exactly that on the real machine at the end of this lesson.
Choosing a delimiter word: pick one that cannot appear at the start of a body line on its own. EOF is the safe default. If your text might contain the word EOF alone on a line, choose something unlikely like __END__ so the shell does not stop early.
No walkthrough this time. Four words are waiting to be filtered: foo, bar, zoo, baz. Feed all four to grep through a heredoc so only the lines containing the letter o survive. Use EOF as the delimiter. Type the opening line; the box replays the body and the result.
prompt: student@linuxcamp:~$ answer: grep o << EOF output: > foo > bar > zoo > baz > EOF foo zoo hint: grep takes its pattern first, then the heredoc: grep <the-letter> << EOF
foo and zoo made it through; bar and baz have no o and were dropped. grep treated the heredoc body exactly like lines from a file. Any filter you have met works the same way on a heredoc.
Three fruits arrive in the wrong order: banana, apple, cherry. Get them printed in alphabetical order using a heredoc, without creating any file. Stick with EOF as the delimiter. There are two honest ways to do it, and the box accepts both.
prompt: student@linuxcamp:~$ answer: sort << EOF ||| cat << EOF | sort output: > banana > apple > cherry > EOF apple banana cherry hint: A heredoc feeds whatever command sits in front of it. Feed the sorting command directly, or feed cat and send it onward through the pipe you know from the redirection lessons.
Either sort << EOF or cat << EOF | sort earns the same output: apple, banana, cherry. The block went straight into the command, was sorted in memory, and no temporary file ever existed. This is the move that saves you from making little scratch files just to feed a filter.
A teammate waves you over: "my terminal is broken, it just eats everything I type." On the screen you find this:
student@linuxcamp:~$ cat << DONE
> one
> two
You know what that > means now. The shell is not broken; it is collecting a heredoc that was never closed. The box below puts you at that prompt. Type the one line that ends the block, runs it, and gives the prompt back.
prompt: > answer: DONE output: one two hint: A heredoc ends when its opening word comes back: alone on the line, spelled exactly the same, nothing else with it.
The block closed, cat printed the two collected lines, and the normal prompt came back. File this rescue away. When a terminal seems frozen and prints > at every line, look up-screen for an unclosed heredoc or an unclosed quote. Then give the shell the ending it is waiting for.
You earned this card. Every row is a move you ran or watched in this lesson:
And the closing-line contract, one more time: the exact same word, alone on its line, flush against the left margin.
The heredoc has three relatives, each with its own lesson ahead. <<- strips leading tabs so scripts can stay neatly indented; it is next. <<< feeds a single one-line string (the herestring). <(...) turns a whole command's output into a file-like input (process substitution). One operator at a time.
Time for a real machine. The lab attached to this lesson, Operation Multiline, boots a real Linux VM just for you. There the > prompts are live: you type the opening line, the body, and the closing word yourself, line by line, with Enter finally working the way this lesson promised.
The mission shows objectives, not commands. You will feed cat a block, write a heredoc straight into a file, and put a different command in front of <<. You will also keep a $HOME literal with a quoted delimiter, and close a block that does not use EOF. Everything you need, you just ran here.
Launch the lab and feed the machine.
Practice The << Heredoc in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.