LINUX BASH SHELL SCRIPT BASICS Part 3:
PUTTING TEXT ON THE SCREEN WITH ECHO AND HERE DOCUMENTS
There are several ways of putting text on the screen for users to read. The simplest is to use the echo command for each line like so:
echo “President Lincoln’s Gettysburg Address”
echo “Fourscore and seven years ago our fathers brought forth,”
echo “on this continent, a new nation, conceived in liberty, and”
echo “dedicated to the proposition that all men are created equal.”
echo “Now we are engaged in a great civil war, testing whether that”
echo “nation, or any nation so conceived, and so dedicated, can long”
echo “endure. We are met on a great battle-field of that war.”
Notice that echo with no text after it simply creates a new empty line. This works but gets cumbersome after just a few lines. Another way to do the same thing is to use one echo command and put the block of text between quotes like so:
echo “President Lincoln’s Gettysburg Address
Fourscore and seven years ago our fathers brought forth,
on this continent, a new nation, conceived in liberty, and
dedicated to the proposition that all men are created equal.
Now we are engaged in a great civil war, testing whether that
nation, or any nation so conceived, and so dedicated, can long
endure. We are met on a great battle-field of that war.
You can opt to add escape codes to echo to enable new lines and colors in conjunction with other utilities like tput. Adding the string $’\n’$ to the first line will add a new line before the text like this:
echo $’\n’$”This text will print on the screen with a blank line above it.”
While the echo command works nicely for single lines and small blocks of text, it can render unpredictable results, especially if there are characters in the text that the shell might see as commands. Here documents are more reliable and easier to work with for large pages of text or tightly formatted text like you’d want to use for menus. You must use some text display utility like cat to show here documents on the screen. You can also use more sophisticated pagers and text editors as well. The basic format of a here document looks like this:
cat << _EOF_ # Text below this command up to _EOF_ will be printed on screen.
President Lincoln’s Gettysburg Address:
“Fourscore and seven years ago our fathers brought forth, on this
continent, a new nation, conceived in liberty, and dedicated to the
proposition that all men are created equal. Now we are engaged in a great
civil war, testing whether that nation, or any nation so conceived, and so
dedicated, can long endure. We are met on a great battle-field of that war.
We have come to dedicate a portion of that field, as a final resting-place
for those who here gave their lives, that that nation might live. It is
altogether fitting and proper that we should do this” …etc
— Gettysburg, PA. November 19, 1863
The “_EOF_” token indicates the end of the here document file.
SENDING SCRIPT OUTPUT AND ERROR MESSAGES TO a LOG FILE
It’s often very useful to have scripts create a log file to let you see what they’re doing and what they’ve done, especially if the script will be run automatically. Well look at some commands from my XBT program and explain how they work to create a log file.
Creating a new log file:
# Generate XBT log file file if not there already:
if [ ! -f /media/$user/XBT_Drive/XBT_Backups/xbt-backup.log ]; then
echo “XBT — External Backup Tool – Log File” \
Creating a new temporary file in /tmp:
date_and_time=”$(date)” # Grabs current date and time and puts in a variable.
echo $’\n’$”Backup sent to XBT_Drive USB from $host by user ‘$user’ on” \
echo “$date_and_time. Any errors?” >> /tmp/backup.log
Using redirection to send only error messages to temporary log file:
(command) 2>> /tmp/backup.log
Using the tee command to append screen output to the temporary log file:
echo “XBT Backup: Successfully completed at $time!” | tee -a /tmp/backup.log
Appending the contents of the temporary log file to the permanent log file:
# Log file is created or appended on XBT_Drive from /tmp:
# (backup.log will be removed from /tmp on next reboot.)
cat /tmp/backup.log >> /media/$user/XBT_Drive/XBT_Backups/xbt-backup.log
Full output for log entry looks like this:
Backup sent to XBT_Drive USB from big-boy by user ‘joe’ on
Fri Jan 11 14:02:58 EST 2019. Any errors?
No errors! 🙂
XBT Backup: Successfully completed at 14:06:41
USING LOOPS IN BASH SCRIPTS
You can setup loops to repeat one task over and over again within a script. A “for loop” is usually the most useful for working with directories full of files or file name arguments at a command line.
This for loop uses the gdebi program to install all the packages in a directory called Packages. This code is phrased in an if statement and is only executed if the directory is found to already exist on the system. It looks like this:
# Install all local .deb packages, if available:
if [ -d “/home/$USER/Downloads/Packages” ]; then
echo “Installing local .deb packages…”
for FILE in ./*.deb
sudo gdebi -n “$FILE”
echo $’\n’$”WARNING! There’s no ~/Downloads/Packages directory.”
echo “Local .deb packages can’t be automatically installed.”
sleep 5 # The script pauses so this message can be read.
This simple for loop grabs file names from the command line arguments and runs a function called “display” on each one and until it’s done:
# Start displaying file(s):
for FILE in “$@”
STOPPING TO ASK FOR USER INPUT WITH THE READ COMMAND
Thus far, we’ve talked about scripts in terms of simple commands that execute automatically. Scripts that act more like programs will usually need to interact with users so they can confirm actions or choose options. This is done with the read command. Read takes input and places it in a variable. Here’s a simple sue of the read command to confirm an action:
echo “Are you sure you want to restore now? [y/N]”
read -n 1 -s choice
The system stops and waits for input from the user. Whatever they type will be entered into the “choice” variable. We can then test for that answer with an if statement to either continue with the program or exit if the user answers with anything other than a lower case ‘y.’ (The capital ‘N’ indicates that it’s the default choice and pressing any key will do the same thing as typing ‘N’.)
if [ “$choice” == “y” ]; then
Commands to complete action.
Commands to skip action or exit the script.
Read can be used to add a pause without asking for specific input:
echo “Press any key to continue.”
read -n 1 -s
Read can catch accidental keyboard input and dump it before moving on to the next command. This is useful when scripts run long processes:
read -t 1 -n 10000 discard
MENU DRIVEN PROGRAMS
BASH scripts that are written to run interactively use greetings and menus to make the script friendly to users. Menus can be constructed using the read command and a series of nested if statements. That works but case statements make wonderful menus. Lets look at the menu for XBT:
XBT — External Backup Tool (Version 3.0)
Main Menu: What would you like to do?
Press the number of your choice:
1 – Backup.
2 – Restore.
3 – Setup XBT Drive.
4 – Get some help.
5 – View backup log. (‘q’ exits.)
6 – Refresh USB Status.
0 – Exit XBT.
Each number corresponds to a script function or a set of simple commands. Here’s the case menu code that makes it work:
read -n 1 -s choice;
case $choice in
6) clear;echo $’\n’$”Refreshing USB Status…”;sleep 2;clear;greeting;;
0) clear;echo $’\n’$”Exiting XBT… Goodbye!”;sleep 2;tput cnorm;exit;;
*) echo “Not a valid choice: Please try again.”;sleep 2;clear;greeting;;
The script does not exit to the prompt. even error messages will dump you back to the greeting menu.
A menu driven program can be run from a terminal with a command or you can create a launcher in your desktop’s menu to start with a click. Terminal programs that are started from the desktop menu will close the terminal when you exit instead of returning to a prompt as they do when launched with a command. The downside of most menu driven scripts is that they can’t be automated or run in a chain with other commands.
I added automated options to XBT after users said they wanted to run it without having to go to the menu to run specific functions.
OTHER TOOLS AND RESOURCES
You can use Git and web sites like GitHub to keep track of versions and share scripts with the world: https://github.com/
My favorite book about BASH is “The Linux Command Line” By William Shotts
You can download it for free: http://linuxcommand.org/tlcl.php
An A-Z Index of the Linux Command Line: https://ss64.com/bash/