Conditional Statements in bash help you make decision. For example, you can tell your script to run this code if certain conditions are met and do that if some other conditions are met. It is one of the most basic concept in bash (and in programming).
In this article, I will talk about basics of How to use Conditional Statements in Bash - if, if-else, if-elif-else, case, and various other types of conditional expressions like -gt
, -lt
, <
, >
, -nt
(file1 is newer than file2), etc.
The if
Statement
The if
statement is the simplest form of a conditional statement in Bash. It executes a code only if a specific condition evaluates to true.
Syntax:
if [[ condition ]]; then
# execute the code if the condition is true
fi
Example:
if [[ 7 -eq 7 ]]; then
echo "Number is 7"
fi
Output:
Number is 7
In this example, the condition 7 -eq 7
evaluates to true, so the code block inside the if
statement is executed.
The if-else
Statement
The if-else
statement extends the if
statement. It executes different code blocks based on whether the condition is true or false.
Syntax:
if [[ condition ]]; then
# if-code to execute if the 'condition' is true
else
# else-code to execute if the 'condition' is false
fi
Example:
if [[ 5 -gt 10 ]]; then
echo "Number is greater than 10"
else
echo "Number is not greater than 10"
fi
Output:
Number is not greater than 10
Explanation:
Since the condition 5 -gt 10
is false, the code block inside the else
branch is executed.
The if-elif-else
Statement
The if-elif-else
statement allows you to test multiple conditions in sequence and execute different code blocks based on the first true condition encountered.
Syntax:
if [[ condition1 ]]; then
# Code to execute if condition1 is true
elif [[ condition2 ]]; then
# Code to execute if condition2 is true
else
# Code to execute if no conditions are true
fi
Example:
if [[ 18 -lt 18 ]]; then
echo "You are a minor"
elif [[ 18 -eq 18 ]]; then
echo "You just turned 18"
else
echo "You are an adult"
fi
Output:
You just turned 18
In this case, the first condition (18 -lt 18
) is false, but the second condition (18 -eq 18
) is true, so the code block corresponding to the elif
branch is executed.
-gt
: greater than
-ge
: greater than or equal to
-lt
: less than
-le
: less than or equal to
The case
Statement
The case
statement provides a way to test multiple conditions against a single value. It is particularly useful when you want to compare a variable against multiple possible values. Here's the basic structure:
case "$variable" in
"value1")
# Code1 to execute for value1
;;
"value2")
# Code2 to execute for value2
;;
*)
# Code3 to execute for all other cases
;;
esac
Let's consider an example:
fruit="apple"
case $fruit in
"apple")
echo "It's an apple";;
"banana")
echo "It's a banana";;
*)
echo "Unknown fruit";;
esac
Output:
It's an apple
In this case, since the value of the fruit
variable is "apple", the corresponding code block is executed.
Note: You need to use *
not "*"
since *
is not a string here.
Numeric Comparison
You can use numeric comparisons to check relationships between numbers. For example:
if [[ 15 -lt 20 ]]; then
echo "15 is less than 20"
fi
Output:
15 is less than 20
In this example, the condition 15 -lt 20
is true, so the code block is executed.
The [
Command (aka test
)
The [
command and test
are basically the same. For example, test -f <file_name>
and [ -f <file_name>]
are the same.
The [
command is a program that evaluates conditional expressions (-n
, -z
, -r
, etc. given below). It is commonly used in conditional statements. For examples see the headings given below.
However, please note that for more advanced conditional tests, it would be more beneficial to use [[]]
and (())
. In my opinion, stick with double brackets because they work most of the time.
-f
and -d
for 'file' or 'directory' checks
You can use the -f
and -d
flags with the [
command to check if a file exists (-f
) or if a directory exists (-d
). For instance:
[ajay@legion bash]$ ls -1
bash_articles.md
bash_brace.md
bash_conditionals.md
bash_loops_article.md
bash_loops.md
bash_parameter_substitution.md
temp.md
testdir
if [ -f "bash_brace.md" ]; then
echo "File exists: bash_brace.md"
fi
if [ -d "testdir" ]; then
echo "Directory exists: testdir"
fi
Output:
File exists: bash_brace.md
Directory exists: testdir
In the first example, the -f
flag checks if the file "bash_brace.md" exists, while in the second example, the -d
flag checks for the existence of the directory "testdir".
String Comparison
String comparisons allow you to compare two strings for equality or inequality. For example:
if [ "smart" = "tech101" ]; then
echo "Strings are equal"
else
echo "Strings are not equal"
fi
Output:
Strings are not equal
In this case, the strings "smart" and "tech101" are not equal, so the code block in the else
branch is executed.
Check if a File Exists and Is Readable
You can use the -r
flag with the [[
command to check if a file exists and is readable:
[ajay@legion bash]$ ls -1
bash_articles.md
bash_brace.md
bash_conditionals.md
bash_loops_article.md
bash_loops.md
bash_parameter_substitution.md
temp.md
testdir
if [[ -r "bash_brace.md" ]]; then
echo "File exists and is readable"
fi
Output:
File exists and is readable
The -r
flag checks if the file "bash_brace.md" exists and has read permission.
Check if a Directory Exists and Is Writable
You can combine the -d
and -w
flags to check if a directory exists and is writable:
$ ls -al
total 96
drwxr-xr-x 3 ajay ajay 4096 Aug 8 14:05 .
drwxr-xr-x 28 ajay ajay 16384 Aug 9 09:24 ..
-rw-r--r-- 1 ajay ajay 11024 Aug 6 15:31 bash_articles.md
-rw-r--r-- 1 ajay ajay 7087 Aug 3 14:19 bash_brace.md
drwxr-xr-x 2 ajay ajay 4096 Aug 8 14:05 testdir
if [[ -d "testdir" && -w "testdir" ]]; then
echo "Directory exists and is writable"
fi
Output:
Directory exists and is writable
In this example, the script checks if both the directory "testdir" exists (-d
flag) and has write permission (-w
flag).
Check if a String Is Empty or non-empty
Use -z
and -n
. Both are exactly opposite of each other.
Just remember the following to avoid the confusion:
-z
means "null"
-n
means "not null"
foo="bar"
if [[ -n "$foo" ]]; then
echo "foo is not null"
fi
Output:
foo is not null
foo="bar"
if [[ -z "$foo" ]]; then
echo "foo is null"
fi
Output:
foo=""
if [[ -n "$foo" ]]; then
echo "foo is not null"
fi
Output:
foo=""
if [[ -z "$foo" ]]; then
echo "foo is null"
fi
Output:
foo is null
Compare Strings for Equality
You can compare two strings for equality using the ==
operator:
str1="smarttech101"
str2="smarttech101"
if [[ "$str1" == "$str2" ]]; then
echo "Strings are equal"
fi
Output:
Strings are equal
In this example, the string variables "str1" and "str2" give equal strings, so the code block is executed.
For variable expansion in bash, look over here
Check if a Variable Is Numeric
You can use regular expressions to check if a variable contains only numeric characters:
var="101"
if [[ "$var" =~ ^[0-9]+$ ]]; then
echo "Variable is numeric"
fi
Output:
Variable is numeric
The regular expression ^[0-9]+$
matches strings that consist of one or more digits.
To learn about regular expression, look at this article
Check if a Command Succeeded
You can use the exit status of a command to determine if it succeeded. If the exit status is zero, the command succeeded:
if command; then
echo "Command succeeded"
fi
Output (assuming command
succeeds):
Command succeeded
In this case, the command
is executed, and if it exits with a status of zero, the code block is executed.
Example:
filename="$HOME/Pictures/example.png"
if wget -qO "$filename" "https://smarttech101.com/test.png"
then
notify-send "Image Downloaded"
else
notify-send "Image Download Failed"
fi
If wget
is unable to download the image, it will fail and notification is popped-up in your Linux machine.
Check if a File Is Executable
You can use the -x
flag to check if a file is executable:
[ajay@legion .my_scripts]$ ls -al test.sh
-rwxr--r-- 1 ajay ajay 315 Aug 4 18:31 test.sh
if [[ -x "test.sh" ]]; then
echo "File is executable"
fi
Output:
File is executable
The -x
flag tests if the file "test.sh" has execute permission.
Compare Numeric Values
You can use arithmetic evaluation to compare numeric values using operators like <
, >
, <=
, >=
, ==
, and !=
. For example:
if (( 5 > 3 )); then
echo "5 is greater than 3"
fi
Output:
5 is greater than 3
In this example, the arithmetic expression 5 > 3
is true, so the code block is executed.
Similarly, <
.
Nested Conditionals
You can nest conditional statements within each other to create more complex decision structures. For example:
var=10
if [[ $var -gt 5 ]]; then
if [[ $var -lt 100 ]]; then
echo "$var is in between 5 and 100"
fi
fi
Output:
10 is in between 5 and 100
In this example, both -gt 5
and -lt 100
are true, so the nested code block is executed.
Advanced File Checks
-ef
checks
Bash provides additional checks to examine files in detail. You can use the -ef
flag to check two files have same device and inode numbers:
file1="file.txt"
file2="link_to_file.txt"
touch "$file1"
ln -s "$file1" "$file2"
if [[ "$file1" -ef "$file2" ]]; then
echo "file1 and file2 with same device and inode numbers"
fi
Output:
file1 and file2 with same device and inode numbers
In this example, both file1
and file2
point to the same content, so the -ef
check succeeds.
-nt
and -lt
checks for files' date comparion
You can also compare file modification times using the -nt
(newer than) and -ot
(older than) flags:
file1="file1.txt"
file2="file2.txt"
touch "$file1"
sleep 2
touch "$file2"
if [[ "$file2" -nt "$file1" ]]; then
echo "file2 is newer than file1"
fi
Output:
file2 is newer than file1
In this example, file2
was touched more recently than file1
, so the -nt
check returns true.
Conversely, you can use the -ot
flag to check if a file is older than another:
file1="file1.txt"
file2="file2.txt"
touch "$file1"
sleep 2
touch "$file2"
if [[ "$file1" -ot "$file2" ]]; then
echo "file1 is older than file2"
fi
Output:
file1 is older than file2
In this scenario, file1
was created earlier than file2
, making the -ot
check true.
Check the status of Shell Options and Variables
You can also use conditional statements to check the status of shell options and variables. For instance, you can check if a shell option is enabled:
optionname="emacs"
if [[ -o "$optionname" ]]; then
echo "Shell option '$optionname' is enabled"
fi
Output:
Shell option 'emacs' is enabled
By default, my bash shell have enabled emacs mode, so testing above option turns out to be true and I get the given output. For optionname="vi"
, no output is generated, because I have not enabled vi
mode.
Similarly, you can check if a shell variable is set:
myvar="Hello"
if [[ -v "myvar" ]]; then
echo "Shell variable 'myvar' is set"
fi
Output:
Shell variable 'myvar' is set
In this example, the script verifies if the shell variable myvar
is set.
You can also determine if a shell variable is a name reference:
declare -n refvar=myvar
if [[ -R "refvar" ]]; then
echo "Shell variable 'refvar' is a name reference"
fi
Output:
Shell variable 'refvar' is a name reference
In this example, the script checks if the variable refvar
is a name reference to another variable.
String Equality and Inequality
You can compare strings for equality using the
=
operator, or for inequality using !=
:
string1="smarttech101"
string2="smarttech101"
if [[ "$string1" == "$string2" ]]; then
echo "Strings are equal"
fi
Output:
Strings are equal
In this case, the strings smarttech101
and smarttech101
are equal, so the code block executes.
On the other hand, checking for inequality:
string1="smart"
string2="tech101"
if [[ "$string1" != "$string2" ]]; then
echo "Strings are not equal"
fi
Output:
Strings are not equal
Since the two strings are not equal, the code block within the if
statement runs.
Lexicographic String Comparison
You can compare strings lexicographically using operators like <
and >
to determine their order. For example, comparing string1
and string2
:
string1="smart"
string2="tech101"
if [[ "$string1" < "$string2" ]]; then
echo "string1 sorts before string2"
fi
Output:
string1 sorts before string2
In this scenario, "smart" appears before "tech101" in lexicographic order, so the code block executes.
Similarly, if string1
is lexicographically greater than string2
:
string1="tech101"
string2="smart"
if [[ "$string1" > "$string2" ]]; then
echo "string1 sorts after string2"
fi
Output:
string1 sorts after string2
Here, "tech101" comes after "smart," so the code block runs.
Conclusion
That's all folks. Thanks for staying this long. If you any question and/or comments put them below. If you want to learn more, read the official documentation about the conditional statements in bash over here.