Project 79. Use Here-Documents in Scripts"How do I use an interactive command in a shell script?" This project explores the use of here-documents in Bash shell scripts. Here-documents provide an easy way to display multi-line messages. They also offer a means of using interactive commands (that normally take input from Terminal) in a shell script by specifying that input will instead be found embedded in the script. Learn More
Learn More
"Talk" in a ScriptA here-document is a clever Bash feature one can employ in shell scripts. It furnishes a technique for redirecting standard input not from a file or pipe, but from the text of the shell script itself. This is best explained by an example. To display a sizeable message from a shell script, we could of course use the echo or cat commands to display text stored in a file. Instead, we'll use cat but supply the text inline as part of the shell script. Redirect from a Here-DocumentThe cat command, in the absence of a filename, reads its input from standard input. In the next example, we use a here-document to redirect standard input to be from the text of the shell script. The following example is taken from a shell script that creates a new Unix group, but for brevity of output, we show only the section that's of interest to us. $ cat new-group #!/bin/bash cat <<EOS The script creates a new Unix group within NetInfo Usage ${0##*/} groupname gid Neither the group name nor the group id must exist EOS $ ./new-group The script creates a new Unix group within NetInfo Usage new-group groupname gid Neither the group name nor the group id must exist Note
Learn More
The start of the region to be read as standard input is marked by <<word. The end of the region is marked by a line containing only word (in which even leading and trailing blanks are not permitted). In this example, the cat command reads the text between <<EOS and EOS and displays it on the terminal line. Using a here-document has several advantages over just displaying the contents of a file. First, the shell script does not need to rely on or know the location of a second file. Second, you'll notice that the parameter ${0##*/} is expanded. All lines of a here-document are subjected to parameter expansion, command substitution, and arithmetic expansion. We could achieve a similar effect by using the echo command, but here-documents have other advantages and uses, which are demonstrated next. Nontrivial shell scripts usually employ indentation to highlight their structure and organization. Your here-documents can follow the natural flow of script indentation, without having that indentation reflected in the text they pass via redirection: Just set the indents within the here-documents using Tab characters, instead of spaces. To enable this useful feature, type <<- instead of << at the beginning of the here-document. Here's an example. $ cat new-group #!/bin/bash cat <<-EOS The script creates a new Unix group within NetInfo Usage ${0##*/} groupname gid Neither the group name nor the group id must exist EOS $ ./new-group The script creates a new Unix group within NetInfo Usage new-group groupname gid Neither the group name nor the group id must exist Although tabs are stripped, spaces are not. This allows space-driven indentation within the here-document text, as in the example above. If you are in the habit of using spaces to indent your shell scripts, revert to using tabs within a here-document. Tip
Control an Interactive CommandIf you want to control an interactive command from a shell script, such as ftp to perform a file transfer, use a here-document to supply the command's input from the text of the script. An interactive command expects to receive its input from standard input (usually, in the form of a human at a keyboard). Let's write a shell script that connects to an FTP server and issues three commands user, ls, and exitto ftp. $ cat ftp-eg ftp -n carcharoth.mayo-family.com <<-EOT user saruman mypassword ls exit EOT Here's what happensautomatically, with no user interventionwhen we run the script. $ ./ftp-eg Connected to carcharoth.mayo-family.com. 220 carcharoth.mayo-family.com FTP server ready. 331 Password required for saruman. ... 150 Opening ASCII mode data connection for '/bin/ls'. total 1 drwxr-xr-x 4 saruman saruman 136 Jun 10 00:21 Public drwxr-xr-x 27 saruman saruman 918 Jun 28 13:17 Sites 226 Transfer complete. 221- Data traffic for this session was 0 bytes in 0 files. Total traffic for this session was 3573 bytes in 1... 221 Thank you for using FTP on carcharoth.mayo-family.com. Tip
Here's a trick in which we use a here-document to form the standard input to a function, read_data, within a script, function-eg. The function requires three pieces of data. $ cat function-eg #!/bin/bash read_data () { read make read model read color } read_data <<-HEREDOC BMW 3 series Blue HEREDOC echo "Make: $make, model: $model, color: $color" $ ./function-eg Make: BMW, model: 3 series, color: Blue |