In Bash, the if..else statement is a fundamental control structure that allows you to make decisions in your shell scripts based on certain conditions. It provides a way to execute different blocks of code depending on whether a given condition evaluates to true or false.
This conditional branching is essential for creating more complex and dynamic scripts that respond intelligently to various situations.
To write if..else in Bash scripts, you need to use the following syntax:
if first-test-commands; then
consequent-commands;
[elif more-test-commands; then
more-consequents;]
[else alternate-consequents;]
fi
There are different test commands syntax depending on the type of condition you want to evaluate and the shell you are using:
[ expression ]
test expression
[[ expression ]]
(( expression ))
Within the condition expression, you can use various operators:
-eq
, -ne
, -lt
, -gt
, -le
, -ge
)=
, !=
, -z
, -n
),-e
, -f
, -d
, -r
, -w
, -x
, etc.)You can use single brackets ([ ]
) in test conditions when you want to use the POSIX test command to check various types of conditions, such as file attributes, string comparisons, numeric comparisons, etc. You need to leave spaces around the brackets and the last argument must be a literal ]
, to match the opening [
.
Single brackets are more portable and compatible with other shells, but they have some limitations and quirks. For example, you need to quote variables to prevent word splitting or globbing, and you need to escape <
and >
for string comparison. For example:
#!/bin/bash
# Testing if a string is empty
string=""
if [ -z "$string" ]; then
echo "The string is empty"
fi
# Testing if two strings are equal
string1="hello"
string2="world"
if [ "$string1" = "$string2" ]; then
echo "The strings are equal"
else
echo "The strings are not equal"
fi
# Testing if two numbers are greater than or equal to each other
num1=10
num2=5
if [ $num1 -ge $num2 ]; then
echo "$num1 is greater than or equal to $num2"
fi
# Testing if a string is lexicographically less than another string
string1="apple"
string2="banana"
if [ "$string1" \< "$string2" ]; then
echo "$string1 comes before $string2"
fi
test
commandIn Bash, the test
command is a built-in utility that evaluates expressions and returns a status (exit code) based on whether the expression is true or false. It is often used to perform various tests and comparisons in shell scripts. The test command is also equivalent to using square brackets [ ]
for testing conditions, as [ ]
is just a symbolic link to the test
command.
#!/bin/bash
# Testing if a file exists and is not a symbolic link
file="test.txt"
if test -e "$file" -a ! -L "$file"; then
echo "$file exists and is not a symbolic link"
fi
# Testing if a directory is writable
dir="mydir"
if test -d "$dir" -a -w "$dir"; then
echo "$dir is a directory and is writable"
fi
# Testing if a string is empty
string=""
if test -z "$string"; then
echo "The string is empty"
fi
# Testing if two strings are equal
string1="hello"
string2="world"
if test "$string1" = "$string2"; then
echo "The strings are equal"
else
echo "The strings are not equal"
fi
# Testing if two numbers are greater than or equal to each other
num1=10
num2=5
if test $num1 -ge $num2; then
echo "$num1 is greater than or equal to $num2"
fi
In Bash, both single square brackets ([ ]
) and double square brackets ([[ ]]
) are used to test conditions in if statements, loops, and other control structures. However, there are some key differences between them, and it’s important to use the appropriate form based on the context and requirements of your script.
Using double square brackets is a Bash-specific extension that allows you to use more advanced features than the single square brackets, which are POSIX compliant and more portable. Some of the advantages of using double square brackets are:
||
and &&
instead of -o
and -a
=~
<
and >
for string comparison without escapingHere is an example of using double square brackets with regular expressions in Bash:
#!/bin/bash
# Check if a string starts with a vowel
string="apple"
if [[ $string =~ ^[aeiou] ]]; then
echo "The string starts with a vowel"
else
echo "The string does not start with a vowel"
fi
The =~
operator inside the double square brackets performs a regular expression match on the left operand (the string) using the right operand (the pattern) as the expression. The ^
in the pattern means the beginning of the string, and [aeiou]
means any of the characters inside the brackets. So the condition is true if the string starts with any vowel.
For most cases, it is generally recommended to use double square brackets in Bash scripts. They offer more capabilities, better readability, and reduced quoting issues compared to single square brackets. However, if you are writing scripts that need to be portable across different shells or if you require strict POSIX compliance, using single square brackets may be more appropriate.
Using double parentheses (( ))
in test conditions in Bash is a way to perform arithmetic evaluation and expansion. You can use them to test numeric expressions and use arithmetic operators such as +
, -
, *
, /
, %
, **
, etc. You can also use them to increment or decrement variables using ++
or --
. You don’t need to use the dollar sign ($
) to reference variables inside double parentheses.
Here are some examples of using double parentheses in test conditions in Bash:
#!/bin/bash
# Testing if a number is even
num=10
if (( num % 2 == 0 )); then
echo "$num is even"
fi
# Testing if a number is positive
num=-5
if (( num > 0 )); then
echo "$num is positive"
else
echo "$num is not positive"
fi
# Testing if two numbers are equal using variables
a=3
b=4
if (( a == b )); then
echo "$a and $b are equal"
else
echo "$a and $b are not equal"
fi
# Incrementing a variable using ++
count=0
(( count++ ))
echo "count is now $count"
You can use multiple conditions in test commands or conditional expressions by using logical operators, such as -a
(and), -o
(or), &&
(and), ||
(or), !
(not), etc. You can also use parentheses to group the conditions and control the order of evaluation. Here are some examples of using multiple conditions:
#!/bin/bash
# Testing if a file exists and is readable or writable
file="test.txt"
if [ -e "$file" ] && [ -r "$file" -o -w "$file" ]; then
echo "$file exists and is readable or writable"
fi
# Testing if a string is not empty and matches a pattern
string="hello"
if [[ -n "$string" && "$string" == [hH][eE][lL][lL][oO] ]]; then
echo "The string is not empty and matches the pattern"
fi
# Testing if a number is positive and even
num=10
if (( num > 0 && num % 2 == 0 )); then
echo "$num is positive and even"
fi
# Testing if a number is not in a range
num=5
if ! (( num >= 10 && num <= 20 )); then
echo "$num is not in the range [10, 20]"
fi
A nested if..else statement in Bash is a way to execute different commands or actions based on multiple conditions. You can use the elif
keyword to add more branches to the if statement, or you can use another if
statement inside the then
or else
clause.
#!/bin/bash
# Checking the type and permissions of a file
file="test.txt"
if [ -e "$file" ]; then
echo "$file exists"
if [ -f "$file" ]; then
echo "$file is a regular file"
if [ -r "$file" ]; then
echo "$file is readable"
fi
if [ -w "$file" ]; then
echo "$file is writable"
fi
if [ -x "$file" ]; then
echo "$file is executable"
fi
elif [ -d "$file" ]; then
echo "$file is a directory"
elif [ -L "$file" ]; then
echo "$file is a symbolic link"
else
echo "$file is of unknown type"
fi
else
echo "$file does not exist"
fi
Bash, POSIX and other shells are related to each other in terms of their history, features, compatibility and standards. Here are some of the main points of their relationship:
Bash is a command-line interpreter that is widely used in Linux and other Unix-like systems. It is a superset of sh, which means it supports all the features of sh
and provides more functionality than sh
. Bash is not a POSIX-compliant shell, but it is intended to be a conformant implementation of the Shell and Utilities portion of the IEEE POSIX specification (IEEE Standard 1003.1).
POSIX is a family of standards that define how a POSIX-compliant operating system should behave and work. It includes a standard for the shell language and utilities, which specifies the syntax, semantics and behavior of various commands and features. POSIX-compliant shells are shells that follow the POSIX standard and can run on any POSIX-compliant system. Some examples of POSIX-compliant shells are dash
, ksh
, zsh
, etc.
Other shells are command-line interpreters that have different features, syntax and behavior than Bash or POSIX shells. They may be compatible or incompatible with Bash or POSIX to some extent, depending on their design and implementation. Some examples of other shells are csh
, tcsh
, fish
, etc.