[Unix-Linux] Shell Scripting - If & Case & Loop & Function
Categories: Unix-Linux
📋 This is my note-taking from what I learned in the Unix/Linux course!
If Statement
The syntax of the if statement is:
if conditional_expression
then
«statements»
fi
Unlike python and similar to most other language, indentation is not necessary, however it does make it easier to see structure in your code.
Old vs New Syntax
- New syntax use double brackets e.g.
[[ ]]
or(( ))
- Old syntax use single bracket e.g.
[ ]
- I feel that the newer syntax will be easier to understand because of our past programming experiences.
- So we will only use the new double brackets syntax.
- The relational operators (
==
,!=
,<
,<=
,>
,>=
) works as expected.
If Statement Using String
#simple 'if statement' using sting
if [["$1" == "hello"]] #we are using string hence [[]]
then
echo "This first argument is 'hello'"
else
echo "This first argument was not 'hello'--"
echo "It was $1."
fi
If Statement Using Numbers
#simple 'if statement' using numbers
if (("$1"%2 == 1)) #we are using number hence (())
then
echo "$1 is an odd number"
else
echo "$1 is an even number"
fi
Nested If Statement
#a nested 'if statement'
if (("$1" > 100)) #we are using number hence (())
then
echo "$1 is a large number"
if (("$1"%2 == 0)) #start of inner if
then
echo "$1 is also even"
fi #end of inner if
else #else block of outer if
echo "$1 is a small number"
fi #end of outer if
More Complex Logic
We can use the Boolean operators ||
and &&
to create more complex logical conditions:
if [["$1" == 'hello']] || [["$1" == 'world']]
then
echo "The first argument was '$1'"
fi
if [["$1" == 'hello']] && [["$2" == 'world']]
then
echo "The first argument was '$1' and the second argument was '$2'"
fi
Operators When Working with Files
Operator | Description |
---|---|
-f |
Checks if the path is a regular file |
-d |
Checks if the path is a directory |
-h |
Checks if the path is a symbolic link |
-b |
Checks if the path is a block device |
-c |
Checks if the path is a character device |
-p |
Checks if the path is a named pipe (FIFO) |
-S |
Checks if the path is a socket |
-s |
Checks if the file exists and has a non-zero size |
-e |
Checks if the path exists, regardless of the type |
#!/bin/bash
# Author: Narendra
# Name: shell03e.sh
# Date: April 17, 2023
# Purpose: To demonstrate File Type Operators
# 1) -f -> Regular file
# 2) -d -> Directory
# 3) -h -> Symbolic link
# 4) -b -> Block device
# 5) -c -> Character device
# 6) -p -> Named pipe
# 7) -S -> Socket
# 8) -s -> non-empty file
# 9) -e -> file exist
var1='file1.txt'
var2='folder1'
var3='shortcut.lnk'
rm -i $var1 #erase the file if it exist
#-i prompts for confirmation before deleting the file represented by $var1
rm -ir $var2 #erase the file if it exist
#-ir prompts for confirmation and recursively deletes the directory represented by $var2 along with its contents
#create the file
touch $var1
#check if the file exist
if [[ -e "$var1" ]]
then
echo "'$var1' does exist"
else
echo "'$var1' does not exist"
fi
#check if it is regular file
if [[ -f "$var1" ]]
then
echo "'$var1' is a regular file"
fi
#check if the file exist and has non-zero size
if [[ -s "$var1" ]]
then
echo "'$var1' is not empty"
else
echo "'$var1' is empty"
fi
#write something to the file
echo "Hello World" > $var1
if [[ -s "$var1" ]]
then
echo "'$var1' is not empty"
else
echo "'$var1' is empty"
fi
#create a directory
mkdir $var2
if [[ -d "$var2" ]]
then
echo "'$var2' is a directory"
fi
#create a link
ln -s $var1 $var2/$var3
#`ln` creates links, `-s` specifies that we wanna create a link, `$var1` is the source file or directory that we wanna create a link to, `$var2/$var3` is the destination path where we wanna create the link -> $var2 is directory path and $var3 is the name of the link
if [[ -h "$var2/var3" ]]
then
echo "'$var2/$var3' is a link"
fi
Case Statement
- Both the case and the if statements serves the same purpose.
- If your solution is a simple comparison, then you are better off using an if statement.
- The case statement is inherently more readably.
-
- Very easy to match patterns against a variable.
- You may use regular-expression and wildcard characters to define patterns.
The syntax of the case statement is:
case expression in
pattern1)
statement1
;;
pattern2)
statement1
;;
pattern3)
statement1
;;
esac
Case Statement
case $1 in
bye)
echo Fine,bye #Fine,bye and "Fine,bye" will produce the same result
;;
hi|hello)
echo Nice to see ya
;;
what*)
echo Fine, bye
;;
*) #default case
echo 'Huh!'
;;
esac
read -p "Enter a command (start, stop, restart): " command
case $command in
start)
echo 'Starting the service...'
;;
stop)
echo 'Stopping the service...'
;;
restart)
echo 'Restarting the service...'
;;
*)
echo 'Invalid command'
;;
esac
Case Statement and If Statement
Case Statement:
case $fruit in
apple)
echo "It's an apple"
;;
orange)
echo "It's an orange"
;;
banana)
echo "It's a banana"
;;
*)
echo "Unknown fruit"
;;
esac
If Statement:
if [[$fruit == "apple"]]
then
echo "It's an apple"
elif [[$fruit == "orange"]]
then
echo "It's an orange"
elif [[$fruit == "banana"]]
then
echo "It's a banana"
else
echo "Unknown fruit"
fi
Loops
-
- Each and every loop must:
-
- First, the variable used in loop condition must be initialized, then execution of the loop begins.
-
- A test (condition) is made at the beginning of each iteration.
-
- The body of loop ends with a statement that modifies the value of the test (condition) variable.
-
- Repeatedly execute a block of statements.
-
- There are three loops:
-
- for loop
-
- while loop
-
- until loop
The syntax of the for loop is:
for var in item1 item2 ... itemN
do
statement1
statement2
statement3
done
For Loop
for num in 1 2 3 4 5
do
echo $num
done
for var in a b c d
do
echo $var
done
For Loop Using a Range
for var in item[246]
do
echo -n $var
done
#Output: item2 item4 item6
for var in item{1...5}
do
echo -n $var
done
#Output: item1 item2 item3 item4 item5
output='code.txt'
rm -i $output #what does '-i' do? Asking permission
files='ls * .sh'
for file in $files
do
echo'================' >> $output
echo $file >> $output
echo'================' >> $output
cat -n $file >> $output #"-n" is number of line
echo >> $output
echo >> $output
echo >> $output
done
Output:
chmod 744 week05d.sh
/.week05d.sh
#print
#shell01a.sh
#shell01b.sh
#shell01c.sh
#shell01d.sh
# .....
./week05d.sh
cat code.txt
#print
#================
#shell01a.sh
#================
#content of file(3 echos)
#================
#shell01b.sh
#================
#content of file(3 echos)
#shell01c.sh
#shell01d.sh
# .....
#week05d.sh
For Loop Using List
for var in list_of_values
do
statement1
statement2
statement3
done
values=(a b c d)
for var in ${values[@]}
do
echo $var
done
Until and While Loop
While loop:
while <<condition>>
do
statement...
done
count=1
while (( $count <= 5 ))
do
echo "Count: $count"
(( count++ ))
done
- The body is processed while the condition is true.
- Prefer this to the
until
loop.
Until loop:
until <<condition>>
do
statement...
done
- The body is processed while the condition is true.
- Advise against using this loop.
Functions
-
- Function definitions in shell scripting is similar to method definition in c#. However, you don’t have to specify formal parameters.
-
- Just use the variables $1, $2 etc. in your function
-
- You may return a value from a function.
-
- You have to access the shell variable $? To obtain the value.
- You may also fake a return value by echo’ing a value and capturing the output of a function in a variable.
- You may use global as well as local variables.
hello1()
{
echo "Hello World"
}
hello2()
{
echo "Hello World from $1"
}
hello3()
{
local sum=`expr $1 + $2`
echo "$sum"
}
hello1
hello2 Narendra
sum=`hello3 5 10`
echo "faking a return value: $sum"
sum=10
hello4()
{
echo -n "Returning the sum of $1 and $2 which is"
return `expr $1 + $2`
}
hello5()
{
echo "****in function - Global variable sum: $sum"
local a=`expr $sum + 123`
echo "****in function - Local variable a: $a"
b=`expr $sum + 321`
echo "****in function - Global variable b: $b"
sum=`expr $sum - 4`
echo "****in function - Global variable sum: $sum"
}
hello4 15 7
echo "$?"
hello5
echo "Global variable sum: $sum"
echo "Local variable a: $a"
echo "Global variable b: $b"
In Unix/Linux shell scripts, $? is a special variable that holds the exit status of the last command executed. It is a way to check whether the command executed successfully or encountered an error.
For example, let’s say we have a command hello4 that we execute. After executing it, the exit status of the command will be stored in $?. If the command executed successfully, the exit status will be 0, indicating success. If there was an error or the command failed, the exit status will be a non-zero value.
Leave a comment