While writing shell script, you might get stuck in the situation where you want to redirect a block of lines from your script to interactive commands like sed, cat, ssh, or ftp.
The purpose of this redirection might vary from situation to situation.
For example, you want to copy the block of lines from the script to a new file, replace the word, or the block of lines are commands that you need to execute in the remote system via ssh.
There is no doubt you can achieve this manually; however, “here document” will make this process way easier than you might think.
Tutorial Details
Description | Here Document (HereDoc) |
Difficulty Level | Low |
Root or Sudo Privileges | No |
OS Compatibility | Ubuntu, Manjaro, Fedora, etc. |
Prerequisites | – |
Internet Required | No |
What is the Here Document (HereDoc) in Linux?
In Bash and also for other implementations of the shell, like ZSH and Fish, you can use the HereDoc to redirect a multi-line or block of lines from the script as an input to interactive commands.
The syntax for writing the HereDoc looks like the following one:
[COMMAND] <<[-] 'DELIMITER'
HERE-DOCUMENT
DELIMITER
Let’s break down the above syntax:
[COMMAND]
: The command is your target interactive command that you will use as an input for redirected multi-line or block of lines from the “HERE-DOCUMENT
” location.<<
: It is the redirection symbol used to redirect anything from target (Stdout) to destination (Stdin).[-]
: If you append this with a redirection symbol, then all the tab spaces will be ignored during redirection, except for the normal space.'DELIMITER'
: The delimiter is like a container; anything defined between the first and last delimiter will be redirected to the target “[COMMAND]
“, and if the delimiter is quoted, it will substitute all variables, commands, and special characters before passing.HERE-DOCUMENT
: It is the multi-line or block of lines that contain strings, variables, commands, and any other type of input that will be redirected to the “[COMMAND]
“.DELIMITER
: The end of the'DELIMITER'
container. White space in front of the delimiter is not allowed.
Note that you can use any string as a delimiter identifier; the most commonly used are EOF, END, Heredoc, Here_document, and CONTAINER.
Here Document (HereDoc) Usage
I will use the following script as an example that contains strings along with environment variables and commands to make things as easy and digestible as possible for beginners.
Current user: $(whoami)
Current Directory: $PWD
Default Shell: $SHELL
Copy the above lines and paste them in the script file with the name “script.sh
“, and don’t forget to give executable permission to your script.
$ chmod u+x script.sh
Output:
Redirecting the Block of Lines to Cat Command
Now, if you want to redirect this whole section of code to interactive commands like “cat”, then edit the script and define the block of lines between the HereDoc.
cat << CONTAINER
Current user: $(whoami)
Current Directory: $PWD
Default Shell: $SHELL
CONTAINER
If you execute the above script, all the lines between the “CONTAINER
” delimiter will be substituted on the output.
$ ./script.sh
Output:
Redirecting the Block of Lines to Cat Command Without Substituting
Enclose the “CONTAINER
” delimiter with single or double quotes to prevent code substitution on the output.
cat << "CONTAINER"
Current user: $(whoami)
Current Directory: $PWD
Default Shell: $SHELL
CONTAINER
When you run the above script, it will prevent parameter expansion and command substitution.
$ ./script.sh
Output:
Redirecting the Block of Lines to Cat Command Without Tabs
If you again edit your file and include space and tabs (to avoid confusion, comments will be removed later).
cat << "CONTAINER"
Current user: $(whoami) #Space is used
Current Directory: $PWD #Tab is used
Default Shell: $SHELL
CONTAINER
The above spaces and tabs will also appear in the output.
$ ./script.sh
Output:
If you want to omit the tabs (not spaces), then append the minus (“–
“) after the redirection, as shown.
cat <<- "CONTAINER"
Current user: $(whoami)
Current Directory: $PWD
Default Shell: $SHELL
CONTAINER
Save and execute the script, and you will find tabs ignored.
$ ./script.sh
Output:
Writing the HereDoc Between the For Loop Statement
If you are using the HereDoc between the for loop statement, then use the “<<-
” redirection symbol that will allow you to indent your code.
if true; then
cat <<- EOF
Line with a tab
EOF
fi
Output:
$ ./script.sh
Output:
Redirecting the Block of Lines to a Text File
Instead of printing the output on the screen, you can redirect it to a text or script file by using the “>
“, “>>
” operators.
Note that if the file does not exist, it will be automatically created in the present directory, and “>
” will overwrite the file and “>>
” will append the line at the end of the file.
cat << CONTAINER > file.txt
Current user: $(whoami)
Current Directory: $PWD
Default Shell: $SHELL
CONTAINER
Output:
$ ./script.sh
$ cat file.txt
Output:
Replacing the String from the Block of Lines
If you want to replace a string from the block of lines and print the output on screen, then pipe the sed command with your delimiter, as shown.
cat <<- CONTAINER | sed 's/Current/Present/'
Current user: $(whoami)
Current Directory: $PWD
Default Shell: $SHELL
CONTAINER
The above command will replace all the “Current
” strings with “Present
“, as shown.
$ ./script.sh
Output:
If you want to save the result in a text file, then redirect the output to a text file (ex: “file.txt
“).
cat <<- CONTAINER | sed 's/Current/Present/' > file.txt
Current user: $(whoami)
Current Directory: $PWD
Default Shell: $SHELL
CONTAINER
Output:
$ ./script.sh
$ cat file.txt
Output:
Writing Multi-line Comments using HereDoc
In Linux, you cannot directly specify comments for a multi-line or block of lines. The only known way is by adding the hash/pound (“#
“) sign at the beginning of each line you want to comment on.
But this method is very inconvenient when adding comments to each line and, especially, when removing them.
However, you can use the HereDoc to redirect the output to an undefined variable that will skip the multi-line or block of lines from execution, as shown.
<< CONTAINER
Current user: $(whoami)
Current Directory: $PWD
Default Shell: $SHELL
CONTAINER
Run the above script, and you will find all codes between “<<CONTAINER
” and “CONTAINER
” are skipped.
$ ./script.sh
Output:
Executing a Series of Commands on the Remote System
If you spend most of the time on a remote system and repetitively execute multiple commands, you can use the HereDoc to execute a block of commands on the remote system at once.
The following is the script that defines the remote system and a series of commands that need to be executed on the target machine.
ssh -T [email protected] << CONTAINER
echo "Current user:" $(whoami)
echo "Current Directory:" $PWD
echo "Default Shell:" $SHELL
CONTAINER
When you execute the above script, all the specified commands between the “CONTAINER
” delimiter will be executed on the “[email protected]
” system, as shown.
$ ./script.sh
Output:
And that was the end of this article.
If you have any question or suggestion related to this topic, feel free to ask it in the comment section.
Join The Conversation
Users are always welcome to leave comments about the articles, whether they are questions, comments, constructive criticism, old information, or notices of typos. Please keep in mind that all comments are moderated according to our comment policy.