Chapter 20: Shell Scripting: Variables and User Input
Chapter Objectives
By the end of this chapter, you will be able to:
- Understand and differentiate between local, environment, and special shell variables.
- Define, assign, and manipulate variables effectively within shell scripts.
- Implement command substitution to capture and use the output of commands within scripts.
- Utilize quoting mechanisms correctly to control word splitting and variable expansion.
- Develop interactive scripts that read and process user input securely.
- Apply these concepts to create practical automation and control scripts on a Raspberry Pi 5.
Introduction
In the world of embedded Linux, automation is not a luxury; it is a fundamental necessity. From initializing hardware at boot to performing routine maintenance tasks or orchestrating complex application deployments, the ability to command the system through scripts is paramount. The shell, the primary interface to the Linux kernel, is also a powerful programming environment. This chapter delves into the foundational elements of that environment: variables and user input. These are the building blocks that transform simple, static command sequences into dynamic, intelligent programs.
Understanding how to store data in variables, how to capture the output of system utilities, and how to prompt a user for information allows an embedded developer to create sophisticated and flexible solutions. Imagine a script that configures network interfaces based on connected hardware, a startup service that calibrates a sensor and stores the calibration data, or a diagnostic tool that queries a user for the specific test they wish to run. These are not just theoretical possibilities; they are everyday tasks in professional embedded development. On the Raspberry Pi 5, where hardware interaction is key, shell scripts serve as the essential glue between the operating system and the physical world. This chapter will equip you with the skills to create that glue, turning your device from a passive computing board into an active, responsive system.
Technical Background
The Essence of Variables in a Shell Environment
At its core, a variable is a named storage location that holds a value. In the context of a shell script, this value is always stored as a string. Even when you assign a number to a variable, the shell treats it as a sequence of characters. This string-centric nature is a defining characteristic of shell scripting and has profound implications for how we handle data. The shell’s primary job is to execute commands, and it uses variables to make this process more flexible and powerful.
Think of a variable as a labeled box. You can put a piece of information (a string) into the box, and later, you can refer to the contents of the box by its label. This simple analogy is the key to unlocking automation. Instead of hardcoding a filename, a network address, or a configuration parameter into a script, we can store it in a variable. This makes the script reusable and maintainable. If the filename changes, we only need to update the variable’s value in one place, rather than searching for every instance of the old filename throughout the script.
There are two primary types of variables you will encounter: local variables and environment variables. The distinction lies in their scope—the context in which they are accessible.
A local variable exists only within the current shell session or script where it was defined. When the script finishes executing, the variable and its value disappear. This is the most common type of variable used for temporary storage within a script’s logic. For example, a loop counter or the temporary storage for a line read from a file would be a local variable.
In contrast, an environment variable is available to the shell session and to any child processes that session creates. When a script is executed, it inherits a copy of its parent shell’s environment. This makes environment variables an excellent mechanism for passing configuration information from a parent process to a child. A classic example is the PATH
variable, which tells the shell where to look for executable programs. When you type a command like ls
, the shell searches the directories listed in the PATH
variable to find the ls
executable. Any script you run will inherit this PATH
, allowing it to find common system utilities without needing to know their absolute location.
Defining a variable is straightforward. The syntax is VARIABLE_NAME="value"
. It is a strong convention in shell scripting to use all uppercase letters for variable names to distinguish them from commands, though this is not a strict requirement. Crucially, there must be no spaces around the equals sign. The statement MY_VAR = "hello"
will fail, as the shell will interpret MY_VAR
as a command to be executed.
To use the value stored in a variable, you must dereference it, which is typically done by prefixing the variable name with a dollar sign ($
). For example, to print the value of MY_VAR
, you would use the command echo $MY_VAR
.
The Critical Role of Quoting
Because the shell is fundamentally string-based and command-oriented, the way it interprets unquoted text can lead to unexpected behavior. The shell performs a process called word splitting, where it breaks a string into separate words (or tokens) based on spaces, tabs, and newlines. It then performs globbing (or filename expansion), where it expands special characters like *
into a list of matching filenames. This is incredibly useful on the command line but can be disastrous inside a script if not handled correctly.
Consider the following: MESSAGE="Hello, world!"
followed by echo $MESSAGE
. The output is Hello, world!
, as expected. Now consider FILENAME="My Important File.txt"
and a command touch $FILENAME
. The shell will split the value of $FILENAME
into four separate words: My
, Important
, File.txt
. The touch
command will then be executed as touch My Important File.txt
, resulting in three separate, empty files instead of the single intended file.
This is where quoting becomes essential. Quoting is the mechanism we use to tell the shell to treat a string as a single unit and to control when and how it expands variables and special characters. There are three forms of quoting:
- Double Quotes (
"
): This is the most common and versatile form of quoting. When you enclose a string in double quotes, word splitting and globbing are suppressed. The shell treats the entire quoted string as a single argument. However, it still performs variable expansion (e.g.,$MY_VAR
), command substitution (covered next), and backslash escaping. Using our previous example,touch "$FILENAME"
would correctly be interpreted astouch "My Important File.txt"
, creating a single file with spaces in its name. This is almost always the desired behavior.Tip: Always enclose your variable references in double quotes (e.g.,echo "$MY_VAR"
) unless you have a specific reason to want word splitting and globbing to occur. This single habit will prevent a significant number of common scripting bugs. - Single Quotes (
'
): Single quotes are the strictest form of quoting. They suppress all expansions. Word splitting, globbing, variable expansion, and command substitution are all turned off. The string is passed to the command literally as-is. For example,echo '$FILENAME'
will print the literal string$FILENAME
, not the value stored in the variable. This is useful when you need to pass a string containing special characters like$
to a program without the shell interfering. - Backslash (
\
): The backslash is used to escape a single character, removing any special meaning it might have. For example,\
will escape the dollar sign, preventing variable expansion.echo \$FILENAME
is equivalent toecho '$FILENAME'
.
Understanding the difference between unquoted, double-quoted, and single-quoted strings is fundamental to writing robust shell scripts.
%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': 'Open Sans'}}}%% graph TD subgraph Shell Parsing Pipeline direction LR A["Start: Command String <br> <i>e.g., touch '$FILE_A' \$FILE_B\</i>"] --> B{Quoting Type?}; B --> C[Single-Quoted <br> <i>...</i>]; C --> D["1- Pass Literal String <br> <i>No expansions</i>"]; B --> E["Double-Quoted <br> <i>...</i>"]; E --> F["1- Variable & Command <br> Substitution <br> <i>e.g., $FILE_B -> My File.txt</i>"]; F --> G["2- Pass as Single Argument"]; B --> H[Unquoted]; H --> I[1- Word Splitting <br> <i>Based on IFS</i>]; I --> J[2- Globbing <br> <i>e.g., * -> file1 file2</i>]; J --> K[3- Variable & Command <br> Substitution]; K --> L[Pass as Multiple Arguments]; end subgraph Final Command Execution D --> Z([Execute Command]); G --> Z; L --> Z; end %% Styling classDef primary fill:#1e3a8a,stroke:#1e3a8a,stroke-width:2px,color:#ffffff; classDef process fill:#0d9488,stroke:#0d9488,stroke-width:1px,color:#ffffff; classDef decision fill:#f59e0b,stroke:#f59e0b,stroke-width:1px,color:#ffffff; classDef endNode fill:#10b981,stroke:#10b981,stroke-width:2px,color:#ffffff; class A primary; class B decision; class C,E,H process; class D,F,G,I,J,K,L process; class Z endNode;
Command Substitution: Capturing Command Output
While variables are excellent for storing static data, we often need to capture dynamic data—the output of another command. This is the purpose of command substitution. It allows you to execute a command and have its standard output replace the command itself, effectively assigning the output to a variable or passing it as an argument to another command.
%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': 'Open Sans'}}}%% graph TD subgraph "Script Execution" A["Start: Script encounters substitution <br> <i>LOG_FILE=sys-$(uname -n).log</i>"] --> B{"Execute Command Inside $()"}; B -- "uname -n" --> C[OS runs uname -n command]; C --> D["Command writes to Standard Output <br> <i>e.g., raspberrypi</i>"]; D --> E{Capture Standard Output}; E --> F["Substitute Output into String <br> <i>sys-<b>raspberrypi</b>.log</i>"]; F --> G["Assign Final String to Variable <br> <i>LOG_FILE = sys-raspberrypi.log</i>"]; end G --> Z[End: Variable is ready to use]; %% Styling classDef primary fill:#1e3a8a,stroke:#1e3a8a,stroke-width:2px,color:#ffffff; classDef process fill:#0d9488,stroke:#0d9488,stroke-width:1px,color:#ffffff; classDef system fill:#8b5cf6,stroke:#8b5cf6,stroke-width:1px,color:#ffffff; classDef endNode fill:#10b981,stroke:#10b981,stroke-width:2px,color:#ffffff; class A primary; class B,E process; class C,D system; class F,G process; class Z endNode;
There are two syntaxes for command substitution: backticks (`
) and the $(...)
form.
- Backticks (
VAR=\
command`. For example,
CURRENT_DATE=`date“. - Dollar-Parentheses (
$(...)
): The modern, preferred syntax isVAR=$(command)
. For example,CURRENT_DATE=$(date)
.
The $(...)
form is universally recommended over backticks. The primary reason is that it can be nested. For instance, echo $(hostname): $(uname -r)
is clean and readable. Trying to nest backticks becomes a nightmare of escaping that is difficult to read and debug.
Command substitution is a cornerstone of system administration and embedded scripting. You can use it to get the current kernel version (uname -r
), find the IP address of a network interface (ip addr show eth0
), or read a sensor value from a command-line utility.
For example, on a Raspberry Pi, you might want to create a log file that is uniquely named with the current date and time. Command substitution makes this trivial:
LOG_FILE="/var/log/sensor_$(date +%Y-%m-%d_%H-%M-%S).log"
echo "Initializing sensor..." > "$LOG_FILE"
Here, the date
command is executed with a format string, and its output (e.g., 2025-07-08_21-54-00
) is substituted directly into the string defining the LOG_FILE
variable. The result is a new, timestamped log file created every time the script runs.
Reading User Input: The read
Command
Interactive scripts require a way to pause and ask the user for information. The built-in shell command for this is read
. In its simplest form, read
takes one line of input from the user (ending when they press Enter) and assigns it to one or more variables.
The basic syntax is read VARIABLE_NAME
. The script will halt execution, wait for the user to type something and press Enter, and then store the entire line of input into VARIABLE_NAME
.
The read
command has several useful options that give you more control over the process:
Combining these tools—variables, quoting, command substitution, and the read
command—provides a complete toolkit for creating powerful, dynamic, and interactive scripts to manage and control your embedded Linux system.
Practical Examples
This section provides hands-on, step-by-step examples that you can run directly on your Raspberry Pi 5. These examples will solidify the theoretical concepts and demonstrate their practical application in an embedded context.
Example 1: System Information Display Script
This first example demonstrates basic variable assignment, command substitution, and the importance of quoting. The script will gather various pieces of system information and display them in a formatted report.
File Structure and Code
Create a new file named sys_info.sh
.
#!/bin/bash
# sys_info.sh - A simple script to display system information.
# This demonstrates variable assignment and command substitution.
# --- Configuration ---
# Use uppercase for variables that act as constants or configuration.
REPORT_TITLE="System Health Report for Raspberry Pi 5"
# --- Data Gathering (Command Substitution) ---
# Use the modern $(...) syntax. It's cleaner and can be nested.
HOSTNAME=$(hostname)
KERNEL_VERSION=$(uname -r)
# Get the current date and time in a specific format.
CURRENT_DATETIME=$(date "+%Y-%m-%d %H:%M:%S")
# Get system uptime. The output of uptime can be long, so we'll capture it all.
SYSTEM_UPTIME=$(uptime)
# Get the CPU temperature from the thermal zone file.
# Note: The file path may vary on different systems.
# We divide by 1000 to get degrees Celsius.
CPU_TEMP_RAW=$(cat /sys/class/thermal/thermal_zone0/temp)
CPU_TEMP_C=$(echo "scale=2; $CPU_TEMP_RAW / 1000" | bc)
# --- Report Generation ---
# Use double quotes to preserve formatting and prevent word splitting.
echo "========================================================"
echo "$REPORT_TITLE"
echo "Report generated on: $CURRENT_DATETIME"
echo "========================================================"
echo ""
echo "Hostname: $HOSTNAME"
echo "Kernel Version: $KERNEL_VERSION"
echo "CPU Temperature: ${CPU_TEMP_C}°C"
echo ""
# The output of uptime contains spaces, so quoting is essential.
echo "System Uptime:"
echo "$SYSTEM_UPTIME"
echo ""
echo "========================================================"
echo "End of Report"
echo "========================================================"
Build and Execution Steps
- Save the Code: Save the code above into a file named
sys_info.sh
in your home directory on the Raspberry Pi 5. - Make it Executable: Open a terminal and run the following command to give the script execution permissions.
chmod +x sys_info.sh
- Run the Script: Execute the script from your terminal.
./sys_info.sh
Expected Output
The output will be a neatly formatted report similar to this (specific values will vary):
========================================================
System Health Report for Raspberry Pi 5
Report generated on: 2025-07-08 21:54:00
========================================================
Hostname: raspberrypi
Kernel Version: 6.6.20+rpt-rpi-2712
CPU Temperature: 45.75°C
System Uptime:
21:54:00 up 2 days, 4:12, 1 user, load average: 0.10, 0.15, 0.09
========================================================
End of Report
========================================================
Code Explanation
#!/bin/bash
: This is the “shebang.” It tells the operating system to execute this file using the Bash interpreter.HOSTNAME=$(hostname)
: This is command substitution. Thehostname
command is run, and its output (e.g., “raspberrypi”) is stored in theHOSTNAME
variable.CPU_TEMP_C=$(echo "scale=2; $CPU_TEMP_RAW / 1000" | bc)
: This is a more complex example. We first read a raw value from a system file. This value is a large integer (e.g.,45750
). We then use theecho
command to create a string representing a mathematical expression and pipe (|
) it to thebc
(basic calculator) utility to perform floating-point arithmetic, storing the result inCPU_TEMP_C
.echo "$REPORT_TITLE"
: This demonstrates the importance of double quotes. If the title contained multiple spaces, they would be preserved. Without quotes, the shell would collapse them into single spaces. The same logic applies toecho "$SYSTEM_UPTIME"
, which is critical for preserving the formatting of theuptime
command’s output.
Example 2: Interactive GPIO Control Script
This example shows how to use the read
command to get user input and control a physical component—an LED connected to a GPIO pin on the Raspberry Pi 5.
Hardware Integration
You will need:
- 1 x LED (any color)
- 1 x 330Ω resistor
- Jumper wires
- A breadboard
Wiring Diagram:
Connect the components as follows:
- Connect the anode (longer leg) of the LED to GPIO pin 17 (physical pin 11) on the Raspberry Pi 5.
- Connect the cathode (shorter leg) of the LED to one end of the 330Ω resistor.
- Connect the other end of the 330Ω resistor to a Ground (GND) pin (e.g., physical pin 9) on the Raspberry Pi 5.
Warning: Always use a current-limiting resistor when connecting an LED to a GPIO pin to avoid damaging both the LED and the Raspberry Pi.
File Structure and Code
We will use Python for the hardware control part, as the RPi.GPIO
library is standard and robust. The shell script will act as an interactive wrapper around the Python script.
1. Python Script (led_control.py)
This script takes a command-line argument (on or off) to control the LED.
# led_control.py
import RPi.GPIO as GPIO
import sys
# --- Configuration ---
LED_PIN = 17 # GPIO pin number
# --- Setup ---
# Use BCM GPIO numbering
GPIO.setmode(GPIO.BCM)
# Set the LED pin as an output
GPIO.setup(LED_PIN, GPIO.OUT)
# Suppress warnings about channel usage
GPIO.setwarnings(False)
# --- Main Logic ---
def main():
"""
Controls the LED based on a command-line argument.
"""
if len(sys.argv) != 2:
print("Usage: python3 led_control.py <on|off>")
sys.exit(1)
command = sys.argv[1].lower()
if command == "on":
GPIO.output(LED_PIN, GPIO.HIGH)
print(f"LED on GPIO {LED_PIN} is now ON.")
elif command == "off":
GPIO.output(LED_PIN, GPIO.LOW)
print(f"LED on GPIO {LED_PIN} is now OFF.")
else:
print(f"Error: Unknown command '{command}'. Use 'on' or 'off'.")
sys.exit(1)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\nExiting. Turning LED off.")
GPIO.cleanup() # Clean up GPIO state
2. Shell Script (interactive_led.sh)
This script provides the user interface.
#!/bin/bash
# interactive_led.sh - An interactive script to control an LED.
# This demonstrates reading user input with 'read'.
# --- Configuration ---
PYTHON_SCRIPT_PATH="./led_control.py"
PYTHON_INTERPRETER="python3"
# --- Functions ---
# It's good practice to put reusable logic into functions.
function show_menu() {
echo "--- LED Control Menu ---"
echo "1. Turn LED ON"
echo "2. Turn LED OFF"
echo "q. Quit"
echo "------------------------"
}
# --- Main Loop ---
while true; do
show_menu
# Use the -p option for a prompt.
read -p "Enter your choice [1, 2, or q]: " user_choice
# Use a case statement for clean menu handling.
case "$user_choice" in
1)
echo "Turning LED ON..."
# Call the Python script with the 'on' argument.
$PYTHON_INTERPRETER "$PYTHON_SCRIPT_PATH" on
;;
2)
echo "Turning LED OFF..."
# Call the Python script with the 'off' argument.
$PYTHON_INTERPRETER "$PYTHON_SCRIPT_PATH" off
;;
q|Q)
echo "Exiting and turning LED off as a safety measure."
# Ensure the LED is off before exiting.
$PYTHON_INTERPRETER "$PYTHON_SCRIPT_PATH" off
break # Exit the while loop.
;;
*) # This is a wildcard that catches any other input.
echo "Invalid option. Please try again."
;;
esac
# Add a newline for better readability between menu loops.
echo ""
done
echo "Program terminated."
Build and Execution Steps
- Install GPIO Library: If not already installed, install the necessary Python library.
pip install RPi.GPIO
- Save the Files: Save the two code blocks above into
led_control.py
andinteractive_led.sh
in the same directory. - Make the Shell Script Executable:
chmod +x interactive_led.sh
- Run the Interactive Script:
./interactive_led.sh
Expected Output and Behavior
%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': 'Open Sans'}}}%% graph TD A[Start: Run ./interactive_led.sh] --> B(Enter Main Loop); subgraph "Loop" direction TB B --> C{Show Menu <br> <i>1. ON, 2. OFF, q. Quit</i>}; C --> D["Prompt User for Input <br><i>read -p ... user_choice</i>"]; D --> E{Evaluate user_choice}; end E -- "Input is '1'" --> F[Call Python Script <br> <i>python3 led_control.py on</i>]; F --> G((LED Turns ON)); G --> B; E -- "Input is '2'" --> H[Call Python Script <br> <i>python3 led_control.py off</i>]; H --> I((LED Turns OFF)); I --> B; E -- "Input is 'q' or 'Q'" --> J[Call Python Script <br> <i>python3 led_control.py off</i>]; J --> K[Exit Loop]; E -- "Other Input" --> L[Show Invalid Option Message]; L --> B; K --> Z[End: Program Terminated]; %% Styling classDef primary fill:#1e3a8a,stroke:#1e3a8a,stroke-width:2px,color:#ffffff; classDef process fill:#0d9488,stroke:#0d9488,stroke-width:1px,color:#ffffff; classDef decision fill:#f59e0b,stroke:#f59e0b,stroke-width:1px,color:#ffffff; classDef endNode fill:#10b981,stroke:#10b981,stroke-width:2px,color:#ffffff; classDef check fill:#ef4444,stroke:#ef4444,stroke-width:1px,color:#ffffff; classDef system fill:#8b5cf6,stroke:#8b5cf6,stroke-width:1px,color:#ffffff; class A primary; class B,C,D process; class E decision; class F,H,J system; class G,I,K,L,Z endNode; class L check;
The script will display a menu. When you enter 1
and press Enter, the LED should turn on. When you enter 2
, it should turn off. Entering q
will exit the script.
--- LED Control Menu ---
1. Turn LED ON
2. Turn LED OFF
q. Quit
------------------------
Enter your choice [1, 2, or q]: 1
Turning LED ON...
LED on GPIO 17 is now ON.
--- LED Control Menu ---
1. Turn LED ON
2. Turn LED OFF
q. Quit
------------------------
Enter your choice [1, 2, or q]: q
Exiting and turning LED off as a safety measure.
LED on GPIO 17 is now OFF.
Program terminated.
Common Mistakes & Troubleshooting
Even with simple concepts like variables and input, several common pitfalls can trip up new and experienced developers alike. Understanding these issues ahead of time can save hours of debugging.
Exercises
These exercises are designed to be completed on your Raspberry Pi 5 and will reinforce the concepts from this chapter.
- Personalized Greeting Script:
- Objective: Write a script that asks for the user’s name and their favorite color, and then prints a personalized greeting.
- Steps:
- Create a script named
greeting.sh
. - Use the
read -p
command to prompt the user for their name and store it in a variable. - Use
read -p
again to ask for their favorite color. - Use
echo
with double-quoted variables to print a message like: “Hello, [Name]! Your favorite color is [Color].”
- Create a script named
- Verification: Run the script and enter different names and colors to ensure the output is correct.
- Simple File Backup Script:
- Objective: Create a script that prompts the user for a filename and creates a timestamped backup of that file.
- Steps:
- Create a script named
backup.sh
. - Prompt the user for a filename to back up.
- Check if the file actually exists (
if [ -f "$FILENAME" ]
). - Use command substitution with the
date
command to create a timestamp string (e.g.,20250708-215400
). - Use the
cp
command to copy the original file to a new file named[original_filename].[timestamp].bak
. - Print a success message showing the new backup filename.
- Create a script named
- Verification: Create a test file, run the script, and verify that a correctly named backup file is created using
ls
.
- Network Status Checker:
- Objective: Write a script that checks if a specific IP address is reachable and reports the status.
- Steps:
- Create a script named
net_check.sh
. - Ask the user for an IP address to check (e.g.,
8.8.8.8
). - Use the
ping
command with-c 1
(to send only one packet) and redirect its output to/dev/null
to suppress it. For example:ping -c 1 "$IP_ADDRESS" > /dev/null 2>&1
. - The
ping
command exits with a status code of 0 on success and non-zero on failure. Check the special variable$?
, which holds the exit status of the last command. - Use an
if
statement to check if$?
is 0. If it is, print that the host is reachable. Otherwise, print that it is unreachable.
- Create a script named
- Verification: Run the script with a known reachable address (like
8.8.8.8
or your router’s IP) and an unreachable one (like10.255.255.1
) to see both messages.
- Timed User Confirmation:
- Objective: Create a script that asks for user confirmation within a time limit.
- Steps:
- Create a script named
confirm.sh
. - Use
read
with the-t 5
(5-second timeout) and-p
options to ask the user “Do you want to proceed? (y/n): “. - Check the exit status (
$?
). If it’s greater than 128, the read command timed out. - If it timed out, print “Timeout! Taking default action.”
- If it did not time out, check the user’s response and print a corresponding message.
- Create a script named
- Verification: Run the script and wait 5 seconds to see the timeout message. Run it again and press
y
within 5 seconds to see the confirmation message.
- GPIO Pin Selector:
- Objective: Modify the
interactive_led.sh
script to ask the user which GPIO pin they want to control. - Special Requirement: This is more advanced. You will need to modify both the shell script and the Python script.
- Steps:
- In
interactive_led.sh
, before the main loop, ask the user to enter a GPIO pin number and store it in a variable. - Modify the Python script
led_control.py
to accept the pin number as a second command-line argument (e.g.,python3 led_control.py 17 on
). - Update the
case
statement in the shell script to pass the selected pin number to the Python script along with theon
/off
command.
- In
- Verification: Rewire your LED to a different GPIO pin (e.g., GPIO 27), run the script, enter the new pin number, and confirm that you can still control the LED.
- Objective: Modify the
Summary
This chapter provided the essential building blocks for creating dynamic and interactive shell scripts, a critical skill for any embedded Linux developer.
- Variables are fundamental for storing and manipulating data. We distinguished between local variables (scoped to the script) and environment variables (inherited by child processes).
- Quoting is non-negotiable for robust scripting. Using double quotes (
"
) around variable expansions prevents common bugs related to word splitting and globbing. - Command substitution (
$(...)
) is the modern and preferred way to capture the output of commands, allowing scripts to react to the system’s dynamic state. - The
read
command is the key to interactivity, enabling scripts to prompt the user for input, with options for displaying prompts (-p
), hiding sensitive data (-s
), and setting timeouts (-t
). - Practical application on the Raspberry Pi 5 shows how these concepts are used to create system utilities and even control hardware, bridging the gap between software and the physical world.
By mastering these concepts, you have moved beyond writing simple, static command sequences and can now create powerful scripts that automate tasks, configure systems, and interact with users and hardware.
Further Reading
- Bash Guide for Beginners – Machtelt Garrels. A classic, thorough guide that covers the fundamentals in great detail. Available on The Linux Documentation Project (tldp.org).
- Advanced Bash-Scripting Guide – Mendel Cooper. An exhaustive reference for more complex scripting techniques. Also available on The Linux Documentation Project (tldp.org).
- The Official Raspberry Pi Documentation. The hardware-specific documentation is invaluable for finding system file paths (like the CPU temperature file) and GPIO information. (raspberrypi.com/documentation)
- GNU Bash Manual. The official, authoritative reference for the Bash shell. It is dense but contains the definitive answer to any question about shell behavior. (gnu.org/software/bash/manual)
man bash
andman read
. The manual pages on your Linux system are the quickest way to look up command syntax and options. Simply typeman bash
in your terminal.- Google’s Shell Style Guide. Provides excellent best practices for writing clean, readable, and maintainable shell scripts, reflecting professional industry standards. (google.github.io/styleguide/shellguide.html)
- Explainshell.com – An interactive web tool where you can paste a shell command and see a visual breakdown of how the shell parses each part. Excellent for deconstructing complex commands.