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 variablename="Sample User"
# Print the variableecho "Hello, $name!"
# Read input from the userecho "Enter your name:"read -r user_nameecho "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 1fi[[ $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 theifblock.
4. Loops in Bash
Loops allow you to repeat tasks multiple times.
#!/bin/bash
# For loopfor i in 1 2 3 4 5; do echo "Iteration: $i"done
# While loopcounter=1while (( counter <= 5 )); do echo "Counter: $counter" ((counter++)) # Increment counterdonefor 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 functiongreet_user() { echo "Hello, $1!" # $1 is the first argument passed to the function}
# Call the function with an argumentgreet_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 itfile="output.txt"printf '%s\n' "This is a sample text" > "$file"printf '%s\n' "Another line of text" >> "$file"
# Check if the file existsif [[ -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 arrayfruits=("apple" "banana" "cherry")
# Print all elements of the arrayecho "All fruits: ${fruits[@]}"
# Access individual elementsecho "First fruit: ${fruits[0]}"
# Loop through the arrayfor fruit in "${fruits[@]}"; do echo "I like $fruit"done4. 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 directlyif ls /home; then echo "Listing succeeded."else echo "Could not list /home." >&2 exit 1fi- An
ifstatement can test a command directly, so there is no need to save$?between commands. exit 1reports failure to the caller. Without an explicitexit, 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 substitutioncurrent_date=$(date)echo "Today's date is: $current_date"$(command): Executescommandand 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 filewhile 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.