0xnhl

Bash Scripting

/ Update
7 min read

Bash (short for “Bourne Again SHell”) is a command-line interpreter and scripting language used to interact with Unix-like operating systems. Created in 1989 for the GNU Project, it serves as the default login shell for many Linux distributions and macOS.

A Bash script is a plain text file containing a sequence of commands that the Bash program executes line by line. It allows you to automate repetitive tasks, manage system operations, and bundle multiple commands into a single executable file.

Syntax#

A bash script always starts with #!/bin/bash at the top of the script. This is so your shell (whatever type of it) knows that it needs to run your file using bash in the terminal.

  • Comments: Comments start with a # and Bash ignores them.
  • Command Order: Commands run one after the other, from top to bottom.
  • Semicolons: Use ; to run multiple commands on the same line.

Example: Simple Bash Script#

#!/bin/bash
# This script prints a greeting message
echo "Hello, World!"
bash

The command “echo” is used to output text to the screen, the same way as “print” in python.
You can also perform normal Linux commands inside your bash script and it will be executed if formatted right.

To run a bash script we must first give it executable permissions, using chmod +x script.sh and then we can run it using ./script.sh.

Parameters#

A bash parameter is any entity that stores values, which includes variables, positional arguments, and special parameters.

Positional Parameters

  • These store arguments passed to your script or function in sequential order.
    • $1, $2, $3: The first, second, and third command-line arguments.
    • ${10}, ${11}: Arguments index 10 and above must be enclosed in curly braces.

Special Parameters

ParameterMeaning & Behavior
$0Returns the path or name of the script being executed.
Use basename "$0" to strip directory paths.
$#Returns the total number of arguments passed.
$?Returns the exit status of the last executed foreground command (0 for success, non-zero for errors).
$$Returns the Process ID (PID) of the current shell or script.
$!Returns the Process ID (PID) of the most recently executed background job.
$-Lists the current option flags enabled in the shell script.
$*Expands all arguments as a single, combined string separated by the first character of IFS.
$@Expands all arguments as separate individual strings (always wrap as "$@" to preserve spaces).

Variables#

Variables in Bash are untyped, case-sensitive, and do not use spaces around the assignment operator (=).

  • Declaration: Define a variable using NAME=value (e.g., USER_NAME="Alice").
  • Referencing: Access the value by prefixing the name with a dollar sign ($USER_NAME or "${USER_NAME}").
  • Variables are local to the current shell session unless exported using export NAME=value to make them environmental variables for child processes.
  • Local variables are only available within the block of code in which they are defined, such as within a function. Global variables are accessible from anywhere in the script.
    Example:
name="John Doe"
echo "Hello, $name!"
bash

Variables can be used in various operations, such as concatenation and arithmetic.

# Concatenation
greeting="Hello, "
name="World"
echo "$greeting$name"

# Arithmetic
num1=5
num2=10
sum=$((num1 + num2))
echo "The sum is $sum"
bash

Bash Data Types#

  • Strings:
    Strings are sequences of characters used to store text. They can be manipulated using various string operations such as concatenation and substring extraction.
  • Numbers:
    Numbers in Bash can be used for arithmetic operations. Bash supports integer arithmetic natively, such as addition, subtraction, multiplication, and division.
  • Arrays:
    Arrays are used to store multiple values in a single variable. Each element in an array is accessed using an index. You can iterate over arrays and modify elements.
  • Associative Arrays:
    Associative arrays allow you to use named keys to access values. They are similar to dictionaries in other programming languages. You can add or remove keys and values.

Arrays#

Arrays can store multiple values, and each value is indexed starting from zero.

# Creating an Array
my_array=("value1" "value2" "value3")
# Accessing Array Elements
echo ${my_array[0]}
# Modify Array Elements
my_array[1]="new_value"
bash

Bash arrays start at index 0, so ${my_array[0]} is the first element.
Other shells differ: in zsh, the default shell on macOS, arrays start at index 1

Conditionals#

If-Else#

The if statement evaluates a condition. If the condition is true, a block of code executes. Otherwise, an alternate block runs (if defined).
The basic syntax of an if statements looks like this

if [ something comparison somethingelse ]
then
	something
else
	something different
fi
bash

Case Statement#

The case statement is used when checking multiple possible values of a variable. It works similar to a switch statement in other programming languages.

name="bob"  
  
case "$name" in  
    "alice") echo "girl" ;;  
    "bob") echo "boy" ;;  
esac
bash

Operators#

Comparison Operators#

  • -eq: Equal to
  • -ne: Not equal to
  • -lt: Less than
  • -le: Less than or equal to
  • -gt: Greater than
  • -ge: Greater than or equal to

String Comparison Operators#

  • ==: Equal to
  • !=: Not equal to
  • <: Less than, in ASCII alphabetical order
  • >: Greater than, in ASCII alphabetical order
  • -n: True if the string is not empty
  • -z: True if the string is empty

Arithmetic Operators#

  • +: Addition
  • -: Subtraction
  • *: Multiplication
  • /: Division
  • %: Modulus (remainder of division)
  • For exponentiation, use external tools like bc or awk.

Logical Operators#

  • &&: Logical AND
  • ||: Logical OR
  • !: Logical NOT

File Test Operators#

  • -e: File or directory exists, regardless of type.
  • -f: Path exists and is a regular file (not a directory or device).
  • -d: Path exists and is a directory.
  • -s: File exists and has a size greater than zero (not empty).
  • -r: File exists and read permission is granted to the current user.
  • -w: File exists and write permission is granted to the current user.
  • -x: File exists and execute permission is granted to the current user.
  • -L: or -h|File exists and is a symbolic link.
  • -O: File exists and is owned by the current user.
  • -G: File exists and belongs to the same group as the current user.
  • -nt: FileA is newer than FileB ([ fileA -nt fileB ]).
  • -ot: FileA is older than FileB ([ fileA -ot fileB ]).
  • -ef: FileA is same as FileB ([ fileA -ef fileB ]).

Output Redirection Operators#

Bash allows redirecting output using special operators, these operators are useful for logging and error handling in automation scripts.

  • >: Redirect stdout to a file (overwrite)
  • >>: Redirect stdout (append)
  • 2>: Redirect stderr (error messages)
  • &>: Redirect both stdout and stderr

Loops#

For loops#

For loops allow you to iterate over a list of items or a range of numbers.
The for keyword is followed by a variable name, a range of values, and a do keyword, which marks the start of the loop block.

for i in {1..5}; do
  echo "Iteration $i"
done
bash

While Loops#

While loops execute a block of code as long as a specified condition is true.
The condition is enclosed in square brackets [ ], and the loop ends with done.

count=1
while [ $count -le 5 ]; do
  echo "Count is $count"
  ((count++))
done
bash

Until loops#

Until loops are similar to while loops, but they execute until a specified condition becomes true.
The condition is enclosed in square brackets [ ], and the loop ends with done.

count=1
until [ $count -gt 5 ]; do
  echo "Count is $count"
  ((count++))
done
bash

Break and continue statements are used to control loop execution. break exits the loop, while continue skips to the next iteration.

Functions#

To define a function in Bash, use the following syntax.

# The function name is followed by parentheses, and the function body is enclosed in curly braces:
my_function() {
  echo "Hello, World!"
}
# We can execute (or call) a function by using its name.
my_function
bash

Functions can accept arguments, return values, and use local variables.

greet() {
  local name=$1
  echo "Hello, $name!"
}
greet "Alice"
bash

You can also return values from functions using echo or the return statement:

add() {
  local sum=$(($1 + $2))
  echo $sum
}
result=$(add 5 3)
echo "The sum is $result"
bash

Debugging#

Bash has a few built in features for debugging:

  • When running at the command line you can do bash -x ./script.sh
    This tells you which lines are working and which lines are not.
     It outputs a + for the command and then the output of what that command executed. If there was an error it would output a - on that line.
  • If you want to debug at a certain point you can insert set -x into your script and set +x to end the section like the following:
echo “hi”
set -x
#this section will be debugged
set +x
bash

Bash Scripting
https://nahil.xyz/vault/linux/bash-scripting/
AuthorNahil Rasheed
Published atAugust 9, 2026
CopyrightCC BY 4.0
DisclaimerThis content is provided strictly for educational purposes only.