The first useful shell script is rarely impressive. It renames a pile of files, checks a service, or turns five commands you keep mistyping into one repeatable task. That small win is also where Bash begins to make sense: it is less about replacing other programming languages and more about joining programs into a reliable workflow.

Understanding Bash and How It Differs from Linux

Bash (Bourne Again SHell) is one of the most widely used command-line interfaces and scripting languages on Unix-like systems. While it is often associated with Linux, Bash is not synonymous with Linux itself. It is commonly installed and is the default interactive shell on some distributions, but that is not universal; /bin/sh may also refer to a different shell. Bash can run on macOS and on Windows through environments such as Windows Subsystem for Linux or Cygwin.

Key Differences Between Bash and Linux

  • Bash is a shell, Linux is a kernel: Linux is the core of an operating system, often referred to as a kernel, responsible for managing system resources and hardware. On the other hand, Bash is a shell, which is an interface between the user and the Linux kernel. Users issue commands through Bash to interact with the system.

  • Bash can run on various systems: While Linux is an operating system kernel, Bash is not tied to Linux. You can install and run Bash on various Unix-like systems (such as macOS), and even on Windows through compatibility layers.

  • Scripting capabilities: Bash is a scripting language that can automate tasks and compose other programs. Linux does not prescribe one scripting language; a system can run scripts through Bash, another shell, Python, Perl, or any other installed interpreter.

What is Bash Scripting?

Bash scripting involves writing a series of commands in a text file and executing them in sequence. Bash scripts allow users to automate repetitive tasks, perform system maintenance, manage files, and much more. This makes it extremely powerful for system administrators and power users.

Let’s start with some basic Bash scripting for beginners and progress towards more advanced examples.

Basic Bash Scripting for Beginners

1. Hello World Script

The simplest Bash script just prints “Hello, World” to the terminal.

#!/bin/bash
# This is a comment. Everything after # is ignored by Bash.
echo "Hello, World!"
  • #!/bin/bash: This is called a “shebang” and indicates that the script should be run using the Bash shell.
  • echo "Hello, World!": This command prints the text to the terminal.

2. Variables and User Input

Bash scripts can use variables to store data and perform tasks based on input.

#!/bin/bash
# Define a variable
name="Sample User"
# Print the variable
echo "Hello, $name!"
# Read input from the user
echo "Enter your name:"
read -r user_name
echo "Hello, $user_name!"

3. Conditional Statements (if-else)

Bash supports conditional statements to perform tasks based on conditions.

#!/bin/bash
echo "Enter a number:"
read -r num
if [[ $num =~ ^-?[0-9]+$ ]] && (( num > 10 )); then
echo "The number is greater than 10"
elif [[ $num =~ ^-?[0-9]+$ ]]; then
echo "The number is 10 or less"
else
echo "Please enter a whole number." >&2
exit 1
fi
  • [[ $num =~ ... ]]: Validates the input before using it in an arithmetic comparison. Without validation, empty or non-numeric input produces a confusing shell error.
  • fi: This ends the if block.

4. Loops in Bash

Loops allow you to repeat tasks multiple times.

#!/bin/bash
# For loop
for i in 1 2 3 4 5; do
echo "Iteration: $i"
done
# While loop
counter=1
while (( counter <= 5 )); do
echo "Counter: $counter"
((counter++)) # Increment counter
done
  • for i in 1 2 3 4 5: This loops over the numbers 1 through 5.
  • while (( counter <= 5 )): Bash arithmetic syntax avoids word-splitting and pathname-expansion problems in numeric tests.

Advanced Bash Scripting

Once you’re comfortable with the basics, you can begin to explore more advanced features of Bash scripting.

1. Using Functions

Functions allow you to encapsulate blocks of code that can be reused.

#!/bin/bash
# Define a function
greet_user() {
echo "Hello, $1!"
# $1 is the first argument passed to the function
}
# Call the function with an argument
greet_user "Taylor"
greet_user "Jordan"
  • greet_user() { ... }: Defines a function.
  • $1: Represents the first argument passed to the function.

2. File Manipulation

Bash scripts are often used for file manipulation tasks.

#!/bin/bash
# Create a new file and write to it
file="output.txt"
printf '%s\n' "This is a sample text" > "$file"
printf '%s\n' "Another line of text" >> "$file"
# Check if the file exists
if [[ -f $file ]]; then
echo "$file exists."
else
echo "$file does not exist."
fi
  • > "$file": Redirects output to a file and overwrites it. Quoting the variable protects paths containing spaces or wildcard characters.
  • >> "$file": Appends output to the quoted path.

3. Working with Arrays

Bash supports arrays, which can store multiple values.

#!/bin/bash
# Define an array
fruits=("apple" "banana" "cherry")
# Print all elements of the array
echo "All fruits: ${fruits[@]}"
# Access individual elements
echo "First fruit: ${fruits[0]}"
# Loop through the array
for fruit in "${fruits[@]}"; do
echo "I like $fruit"
done

4. Error Handling and Exit Codes

You can handle errors in Bash using exit codes. A non-zero exit code indicates that an error occurred.

#!/bin/bash
# Test the command directly
if ls /home; then
echo "Listing succeeded."
else
echo "Could not list /home." >&2
exit 1
fi
  • An if statement can test a command directly, so there is no need to save $? between commands.
  • exit 1 reports failure to the caller. Without an explicit exit, a script normally returns the status of the last command it executed. An earlier failure can therefore be hidden if a later command succeeds, which is why deliberate error handling matters.

5. Command Substitution

You can capture the output of a command and use it as a variable.

#!/bin/bash
# Command substitution
current_date=$(date)
echo "Today's date is: $current_date"
  • $(command): Executes command and stores its output in a variable.

6. Advanced Looping with Files

A script can process files line by line.

#!/bin/bash
# Loop through each line of a file
while IFS= read -r line || [[ -n $line ]]; do
echo "Line: $line"
done < "file.txt"
  • IFS= read -r line: Reads a line without trimming surrounding whitespace or treating backslashes specially. The extra condition also processes a final line that has no trailing newline.

Conclusion

Bash is at its best when it connects existing commands, checks their results, and turns a familiar manual sequence into something repeatable. Quote expansions, handle input carefully, and make failures visible. When the script grows into a large application with complex data structures or extensive error recovery, that is usually a sign to keep Bash as the coordinator and move the heavier logic into another language.