How to use “Documents Here” in Bash on Linux

A terminal window on a Linux computer system.
Fatmawati Achmad Zaenuri / Shutterstock

The strange “docs here” allow you to use input / output redirection within Bash scripts on Linux. They are a great way to automate the commands you need to run on a remote computer.

Here Documents

Many commands in Linux have two or three letter names. This is partly what gives rise to the idea that Linux is difficult to learn and full of arcane commands. But one of the strangest names in Linux is not one of the cryptically short ones. “Here the documents” are not documents, and it is not very clear what the “here” refers to.

They are a relatively dark construction, but they are useful. Of course, this is Linux, so there is more than one way to skin a cat. Some of the functions provided by these documents can be reproduced in other ways. These alternative methods are often more complicated. In programming and scripting, “more complicated” also means “more error prone” and that your code is more difficult to maintain.

Where documents really excel here is in automating commands that you want to send to a remote computer from an established connection from within a script. Making the connection is easy, but once the connection is made, how do you “pump” your commands from your script to the shell on the remote computer? Here the docs allow you to do that very simply.

Document Basics Here

The idiomatic representation of a document here looks like this:

COMMAND << limit_string
 .
 .
text 
data
variables
.
.
limit_string
  • COMMAND: Can be any Linux command that accepts redirected input. Note the echo command does not accept redirected input. If you need to write on the screen, you can use the cat command, that makes.
  • <: The redirect operator.
  • limit_string: This is a label. It can be whatever you want as long as it doesn’t appear in the list of data you are redirecting to the command. It is used to mark the end of the list of text, data and variables.
  • Data list: A list of data to be sent to the command. It can contain commands, text, and variables. The contents of the data list are entered into the command one line at a time until _limit_string is found.

You will probably see examples in here documents that use “EOF” as the boundary string. We do not favor that approach. It works, but “EOF” means “End of file”. Aside from the rare case where a starter document is the last thing in a script file, “EOF” is being misused.

It will make your scripts much more readable if you use a boundary string that refers to what you are doing. If you are sending a series of commands to a remote computer via Safe cover (SSH), a limit string called something like “_remote_commands” would make a lot of sense. It is not necessary to start with an underscore “_“character. We do it because he marks them as something out of the ordinary in his script.

Simple examples

You can use documents here on the command line and in scripts. When you type the following in a terminal window, you will see a “>“Line continuation message every time you press” Enter “. When you type the boundary string” _end_of_text “and press” Enter “, the list of websites is changed to cat, and are displayed in the terminal window.

cat << _end_of_text 
How-To Geek 
Review Geek 
LifeSavvy 
CloudSavvy IT
MindBounce
_end_of_text

That’s not the most valuable exercise, but it shows that nothing is sent to the command until the entire data list is collected and the bounding string is found. The cat The command receives no input until you enter the boundary string “_end_of_text” and press the “Enter” key.

We can do the same in a script. Write or copy this example into an editor, save the file as “heredoc-1.sh” and close the editor.

#!/bin/bash

cat << "_end_of_text"
Your user name is: $(whoami)
Your current working directory is: $PWD
Your Bash version is: $BASH_VERSION
_end_of_text

As this article continues, each time you create a script, you will need to make it executable before it runs. In each case, use the chmod command. Replace the name of the script in each example with the name of the script used here.

chmod +x heredoc-1.sh

This script contains two environment variables, $PWD and $BASH_VERSION. The names of the environment variables are replaced with their data values ​​(current working directory and Bash version) when the script runs.

The script also uses command substitution about him whoami command. The command name is replaced by its own output. The output of the entire script is written to the terminal window using the cat command. We run the script calling it by name:

./heredoc-1.sh

If you modify the script and put the boundary string in the first line of the document here in quotes ” " “, The data list is passed to the document command here literally. Variable names are displayed instead of variable values, and command substitution will not be performed.

#!/bin/bash

cat <<- "_end_of_text"
Your user name is: $(whoami)
Your current working directory is: $PWD
Your Bash version is: $BASH_VERSION
_end_of_text

Tab character handling

By default, the tab characters in your data list will be preserved and written to the terminal window. Copy and save this example as “heredoc-2.sh”. Make it executable using the chmod command. Edit the indented lines to ensure that they have one or two tab characters at the beginning of the line instead of a series of spaces.

#!/bin/bash

cat << _end_of_text
Your user name is: $(whoami)
  Your current working directory is: $PWD
    Your Bash version is: $BASH_VERSION
_end_of_text
./heredoc-2.sh

Tabs are written in the terminal window.

Adding a dash “-”For the redirect operator, the document here will ignore leading tab characters. Save this example as “heredoc-3.sh” and make it executable.

#!/bin/bash

cat <<- _end_of_text
Your user name is: $(whoami)
  Your current working directory is: $PWD
    Your Bash version is: $BASH_VERSION
_end_of_text
./heredoc-3.sh

The tabs are ignored. This may seem trivial, but it is a good way to deal with the initial tabs due to the indented sections of the scripts.

Loops and other logic constructs are often indented. If your document here is contained in an indented section of a script, use a dash “-With the redirect operator you eliminate formatting problems caused by leading tab characters.

#!/bin/bash

if true; then
  cat <<- _limit_string
  Line 1 with a leading tab.
  Line 2 with a leading tab.
  Line 3 with a leading tab.
  _limit_string
fi

Redirect to a file

The output of the command used with the document here can be redirected to a file. Use the “>“(Create the file) or”>>“(Create the file if it doesn’t exist, add it to the file if it exists) redirect operators after the boundary string in the first line of the document here.

This script is “heredoc-4.sh”. It will redirect your output to a text file called “session.txt”.

#!/bin/bash

cat << _end_of_text > session.txt
Your user name is: $(whoami)
Your current working directory is: $PWD
Your Bash version is: $BASH_VERSION
_end_of_text
./heredoc-4.sh
cat session.text

Pipe the output to another command

The output of the command used in a document here can be piped as input to another command. Use the pipe “|“Operator after the boundary string in the first line of the document here. We are going to pipe the output of the here document command, cat, inside sed. We want replace all occurrences from the letter “a” with the letter “e”.

Name this script “heredoc-5.sh”.

#!/bin/bash

cat << _end_of_text | sed 's/a/e/g'
How
To
Gaak
_end_of_text
./heredoc-5.sh

“Gaak” corrects to “Geek”.

Sending parameters to a function

The command used with a document here can be a function in the script.

This script passes some data from the vehicle to a function. The function reads the data as if it were entered by a user. The variable values ​​are then printed. Save this script as “heredoc-6.sh”.

#!/bin/bash

# the set_car_details() function
set_car_details ()
{
read make
read model
read new_used
read delivery_collect
read location
read price
}

# The here document that passes the data to set_car_details()
set_car_details << _mars_rover_data
NASA
Perseverance Rover
Used
Collect
Mars (long,lat) 77.451865,18.445161
2.2 billion
_mars_rover_data

# Retrieve the vehicle details
echo "Make: $make"
echo "Model: $model"
echo "New or Used: $new_used"
echo "Delivery or Collection: $delivery_collect"
echo "Location: $location"
echo "Price $: $price"
./heredoc-6.sh

Vehicle details are written in the terminal window.

Create and send an email

We can use a document here to compose and send an email. Note that we can pass parameters to the command in front of the redirect operator. They were using linux mail command for send an email through the local mail system to the user account named “dave”. The -s The option (subject) allows us to specify the subject of the email.

This example forms the script “heredoc-7.sh”.

#!/bin/bash

article="Here Documents"

mail -s 'Workload status' dave << _project_report
User name: $(whoami)
Has completed assignment:
Article: $article
_project_report
./heredoc-7.sh

There is no visible output from this script. But when we check our mail, we see that the email was composed, sent and delivered.

mail

Using documents here with SSH

Here the docs are a powerful and convenient way to run some commands on a remote computer once an SSH connection has been established. If you have configured SSH keys between the two computers, the login process will be completely automatic. In this quick and dirty example, you will be prompted for the password of the user account on the remote computer.

This script is “heredoc-8.sh”. We are going to connect to a remote computer called “remote-pc”. The user account is named “dave”. We are using the -T (disable pseudo-terminal assignment) because we don’t need an interactive pseudo-terminal to be assigned to us.

In the “do some work here” section of the script, we could pass a list of commands, and these would be executed on the remote computer. Of course, you could just call a script that was on the remote computer. The remote script could contain all the commands and routines that you want to run.

All our script, heredoc-8.sh, is going to do is update a connection record on the remote computer. The user account and the date and time stamp are recorded in a text file.

#!/bin/bash

ssh -T dave@remote-pc.local << _remote_commands

# do some work in here

# update connection log
echo $USER "-" $(date) >> /home/dave/conn_log/script.log
_remote_commands

When we execute the command, we are asked for the password of the account in the remote computer.

./heredoc-8.sh

Some information about the remote computer is displayed and we return to the command prompt.

About him remote computer, we can use cat to check the connection log:

cat conn_log/script.log

Each connection is listed for us.

RELATED: How to create and install SSH keys from the Linux Shell

Strange name, cool features

Here the documents are quirky but powerful, especially when used to send commands to a remote computer. It would be very easy to script a backup routine using rsync. The script could then connect to the remote computer, check the remaining storage space, and send an alert email if the space was running low.

RELATED: How to Backup Your Linux System

Leave a Reply