Shell scripting is a powerful tool for automating tasks, managing systems, and enhancing your productivity within a Linux or Unix-like environment. Bash, the Bourne Again Shell, is the most common shell and provides a robust scripting language. This chapter will introduce you to the fundamentals of Bash scripting and demonstrate its capabilities through practical examples.
1. Introduction to Bash Scripting
A shell script is a plain text file containing a series of commands that the shell executes sequentially. These commands can include system utilities, shell built-ins, and even other scripts.
1.1. Creating and Executing Scripts
- Create a script: Open a text editor and write your commands.
- Save the script: Save the file with a .sh extension (e.g., my_script.sh).
- Make it executable: Use chmod +x my_script.sh.
- Run the script: Execute it from the terminal using ./my_script.sh.
1.2. The Shebang (#!)
The first line of a script, the shebang, specifies the interpreter to use. For Bash scripts, it’s #!/bin/bash or #!/bin/sh (for more basic shell compatibility).
2. Basic Scripting Concepts
2.1. Variables
Variables store data. Assign values using variable_name=value. Access them using $variable_name or ${variable_name}.
Bash
#!/bin/bash
name="John Doe"
echo "Hello, $name!"
2.2. Input/Output
- echo: Prints text to the console.
- read: Reads input from the user.
Bash
#!/bin/bash
read -p "Enter your name: " name
echo "Your name is: $name"
2.3. Conditional Statements (if, elif, else)
Control the flow of execution based on conditions.
Bash
#!/bin/bash
read -p "Enter a number: " num
if [ $num -gt 0 ]; then
echo "Positive number."
elif [ $num -lt 0 ]; then
echo "Negative number."
else
echo "Zero."
fi
2.4. Loops (for, while)
Repeat a block of code.
- for loop: Iterates over a list of items.
Bash
#!/bin/bash
for i in 1 2 3 4 5; do
echo "Number: $i"
done
- while loop: Executes as long as a condition is true.
Bash
#!/bin/bash
count=1
while [ $count -le5 ]; do
echo "Count: $count"
count=$((count + 1))
done
3. Practical Scripting Examples
Here are the scripts from your previous requests, integrated into this chapter:
3.1. Reversing a Number
Bash
#!/bin/bash
read -p "Enter a number: " num
reversed=""
original_num=$num
while [ $num -gt 0 ]; do
digit=$((num % 10))
reversed="$reversed$digit"
num=$((num / 10))
done
echo "Original number: $original_num"
echo "Reversed number: $reversed"
3.2. Displaying Username as Banner
Bash
#!/bin/bash
username=$(whoami)
banner=$(banner "$username")
if [[ -n "$banner" ]]; then
echo "$banner"
else
echo "Error: banner command not found or failed."
fi
3.3. Listing Directories
Bash
#!/bin/bash
for item in *; do
if [ -d "$item" ]; then
echo "$item"
fi
done
3.4. Using ls and more Based on File Type
Bash
#!/bin/bash
if [ $# -ne 1 ]; then
echo "Usage: $0 "
exit 1
fi
filename="$1"
if [ -d "$filename" ]; then
ls -l "$filename"
elif [ -f "$filename" ]; then
more "$filename"
else
echo "Error: '$filename' is not a file or directory."
exit 1
fi
3.5. Copying/Overwriting a File
Bash
#!/bin/bash
if [ $# -ne 2 ]; then
echo "Usage: $0 "
exit 1
fi
source_file="$1"
destination_file="$2"
if [ ! -f "$source_file" ]; then
echo "Error: Source file '$source_file' does not exist."
exit 1
fi
cp "$source_file" "$destination_file"
if [ $? -eq 0 ]; then
echo "File '$source_file' copied to '$destination_file' successfully."
else
echo "Error: Failed to copy file '$source_file' to '$destination_file'."
exit 1
fi
3.6. Word Length
Bash
#!/bin/bash
read -p "Enter a word: " word
length=${#word}
echo "The word '$word' is $length characters long."
3.7. Appending Line to File
Bash
#!/bin/sh
if [ $# -ne 2 ]; then
echo "Usage: $0 "
exit 1
fi
filename="$1"
line_to_append="$2"
if [ ! -f "$filename" ]; then
echo "Error: File '$filename' does not exist."
exit 1
fi
echo "$line_to_append" >> "$filename"
if [ $? -ne 0 ]; then
echo "Error: Failed to append line to '$filename'."
exit 1
fi
line_count=$(wc -l < "$filename")
echo "Line appended successfully. Total lines in '$filename': $line_count"
3.8. User UID and Login Count
Bash
#!/bin/bash
if [ $# -ne 1 ]; then
echo "Usage: $0 "
exit 1
fi
username="$1"
uid=$(id -u "$username" 2>/dev/null)
if [ -z "$uid" ]; then
echo "Error: User '$username' not found."
exit 1
fi
login_count=$(lastb "$username" | wc -l)
successful_logins=$(last "$username" | wc -l)
total_logins=$((login_count + successful_logins))
echo "Username: $username"
echo "UID: $uid"
echo "Total Logins (successful and failed): $total_logins"
echo "Successful Logins: $successful_logins"
echo "Failed Logins: $login_count"
3.9. User Information from UID
Bash
#!/bin/bash
if [ $# -ne 1 ]; then
echo "Usage: $0 "
exit 1
fi
uid="$1"
username=$(getent passwd "$uid" | cut -d: -f1)
if [ -z "$username" ]; then
echo "Error: UID '$uid' not found."
exit 1
fi
fullname=$(getent passwd "$uid" | cut -d: -f5 | cut -d, -f1)
home_dir=$(getent passwd "$uid" | cut -d: -f6)
shell=$(getent passwd "$uid" | cut -d: -f7)
primary_group=$(getent group "$(getent passwd "$uid" | cut -d: -f4)" | cut -d: -f1)
secondary_groups=$(getent group | awk -F: '$4 ~ /'"$uid"'/ {print $1}')
echo "Username: $username"
echo "Full Name: $fullname"
echo "Home Directory: $home_dir"
echo "Shell: $shell"
echo "Primary Group: $primary_group"
if [ -n "$secondary_groups" ]; then
echo "Secondary Groups: $secondary_groups"
fi
3.10. Mail Merge Facility
Bash
#!/bin/bash
# Mail Merge Script
# Usage: mail_merge.sh
# Check for correct number of arguments
if [ $# -ne 4 ]; then
echo "Usage: $0 "
exit 1
fi
TEMPLATE_FILE="$1"
DATA_FILE="$2"
SUBJECT="$3"
OUTPUT_DIR="$4"
# Check if template and data files exist
if [ ! -f "$TEMPLATE_FILE" ]; then
echo "Error: Template file '$TEMPLATE_FILE' not found."
exit 1
fi
if [ ! -f "$DATA_FILE" ]; then
echo "Error: Data file '$DATA_FILE' not found."
exit 1
fi
# Check if output directory exists, if not, create it
if [ ! -d "$OUTPUT_DIR" ]; then
mkdir -p "$OUTPUT_DIR"
fi
#Read data file line by line
while IFS=',' read -r name email address; do
# Create output file name
OUTPUT_FILE="$OUTPUT_DIR/mail_to_$email.txt"
# Replace placeholders in template file
cat "$TEMPLATE_FILE" | sed \
-e "s/{{NAME}}/$name/g" \
-e "s/{{EMAIL}}/$email/g" \
-e "s/{{ADDRESS}}/$address/g" > "$OUTPUT_FILE"
# Send email (optional - requires mail command or similar)
# echo "Mail content generated in $OUTPUT_FILE"
# mail -s "$SUBJECT" "$email" < "$OUTPUT_FILE"
done < "$DATA_FILE"
echo "Mail merge completed. Output files generated in '$OUTPUT_DIR'."
exit 0
Explanation and Usage:
- Script Arguments:
<template_file>
: The path to the template file containing placeholders like{{NAME}}
,{{EMAIL}}
, and{{ADDRESS}}
.<data_file>
: The path to a CSV (comma-separated values) file containing the data to be merged. The first line of the CSV file should bename,email,address
. Subsequent lines contain the data for each recipient.<subject>
: The subject line for the emails.<output_dir>
: The directory where the generated mail files will be saved.
- Error Handling:
- The script checks if the correct number of arguments are provided.
- It verifies that the template and data files exist.
- It creates the output directory if it doesn’t already exist.
- Data Processing:
- The
while IFS=',' read -r name email address; do ... done < "$DATA_FILE"
loop reads the data file line by line, splitting each line into thename
,email
, andaddress
variables using commas as delimiters. - For each line, it creates an output file named
mail_to_<email>.txt
in the specified output directory. - The
cat "$TEMPLATE_FILE" | sed ... > "$OUTPUT_FILE"
command reads the template file and usessed
to replace the placeholders with the corresponding data from the current line.
- The
- Optional Email Sending:
- The commented-out
mail
command demonstrates how to send the generated emails. You’ll need to have themail
command (or a similar mail utility) installed on your system. - Uncomment the lines to enable email sending.
- The commented-out
Example Template File (template.txt):
Dear {{NAME}},
This is a personalized message for you.
Your email address is: {{EMAIL}}
Your address is: {{ADDRESS}}
Sincerely,
The Team
Example Data File (data.csv
):
Code snippet
name,email,address
John Doe,john.doe@example.com,123 Main St
Jane Smith,jane.smith@example.com,456 Oak Ave
Peter Jones,peter.jones@example.com,789 Pine Ln
How to Run the Script:
- Save the script to a file (e.g.,
mail_merge.sh
). - Make the script executable:
chmod +x mail_merge.sh
. - Run the script:
./mail_merge.sh template.txt data.csv "Your Subject" output_mails
.
This will generate three files in the output_mails
directory: mail_to_john.doe@example.com.txt
, mail_to_jane.smith@example.com.txt
, and mail_to_peter.jones@example.com.txt
.
Leave a Reply