Bash Scripting
Download some example scripts
note
You can download some example scripts that are used here:
wget https://linux-cli.fs.al/apps/part1.tgz
tar xfz part1.tgz
cd part1/ && ls
1. Hello world
-
nano hello.sh
:#!/bin/bash
echo "Hello World!"
echo "How are you today?"chmod +x hello.sh
./hello.sh -
nano hello.sh
:#!/bin/bash
echo "
Hello World!
How are you today?
" -
nano hello.sh
:#!/bin/bash
cat <<EOF
Hello World!
How are you today?
EOF
2. Loops: for
, while
, until
-
nano count.sh
:#!/bin/bash
for i in {1..5}; do
echo $i
done
echo "Finished."Replace
{1..5}
with1 2 3 4 5
, then witha b c d e
. -
nano count.sh
:#!/bin/bash
for ((i=1; i<=5; ++i)); do
echo $i
done
echo 'Finished.' -
nano count.sh
:#!/bin/bash
count=1
while ((count <= 5)); do
echo $count
count=$((count + 1))
done
echo "Finished." -
nano count.sh
:#!/bin/bash
count=1
while [[ $count -le 5 ]]; do
echo $count
count=$((count + 1))
done
echo "Finished." -
nano count.sh
:#!/bin/bash
count=1
until [[ $count -gt 5 ]]; do
echo $count
count=$((count + 1))
done
echo "Finished."
3. Branching with if
-
nano modulo.sh
:#!/bin/bash
for ((i = 0; i <= 20; ++i)); do
if ((i % 5 == 0)); then
printf "<%d> " "$i"
else
printf "%d " "$i"
fi
done
printf "\n" -
nano modulo.sh
:#!/bin/bash
for ((i = 0; i <= 20; ++i)); do
if ((i % 5 == 0)); then
printf "<%d> " "$i"
elif ((i % 3 == 0)); then
printf "[%d] " "$i"
else
printf "%d " "$i"
fi
done
printf "\n"
4. Read input
-
Testing integers:
test-int-1.sh
#!/bin/bash
echo -n "Please enter an integer -> "
read int
if [[ ! $int =~ ^-?[0-9]+$ ]]; then
echo "Input value is not an integer." >&2
exit 1
fi
if ((int == 0)); then
echo "$int is zero."
else
if ((int < 0)); then
echo "$int is negative."
else
echo "$int is positive."
fi
if (( ((int % 2)) == 0)); then
echo "$int is even."
else
echo "$int is odd."
fi
fi -
Reading a password:
read-pass.sh
#!/bin/bash
# -e: use readline to get the input
# -p: display a prompt
# -i: provide a default reply
read -e -p "What is your user name > " -i $USER username
echo "Welcome '$username'"
# -t: timeout (in seconds)
# -s: silent (do not echo characters to the display as they are typed)
# -p: display a prompt
if read -t 10 -sp "Enter your secret passphrase > " secret_pass
then
echo -e "\nYour secret passphrase is '$secret_pass'"
else
echo -e "\nInput timed out" >&2
exit 1
fi
5. Parameters
-
params.sh
:#!/bin/bash
# view command line parameters
echo "
\$0 = $0
\$1 = $1
\$2 = $2
\$3 = $3
\$4 = $4
\$5 = $5
\$6 = $6
\$7 = $7
\$8 = $8
\$9 = $9
Number of arguments: $#
"./params.sh a b c d
-
Calculate the Fibonacci numbers:
fibo.sh
#!/bin/bash
N=$1
if [[ -z $N ]]; then
echo "Usage: $0 <n>" >&2
exit 1
fi
[[ $N == 0 ]] && echo 0 && exit
[[ $N == 1 ]] && echo 1 && exit
f0=0
f1=1
for ((i=1; i<N; i++)); do
fib=$((f0 + f1))
f0=$f1
f1=$fib
done
echo $f1./fibo.sh
for i in {0..10}; do ./fibo.sh $i; done
./fibo.sh 100
6. Functions
-
Testing integers, with a function and a loop:
test-int-2.sh
#!/bin/bash
check() {
local int=$1
if [[ ! $int =~ ^-?[0-9]+$ ]]; then
echo "Input value is not an integer." >&2
return 1
fi
if ((int == 0)); then
echo "$int is zero."
else
if ((int < 0)); then
echo "$int is negative."
else
echo "$int is positive."
fi
if (( ((int % 2)) == 0)); then
echo "$int is even."
else
echo "$int is odd."
fi
fi
}
while true; do
echo
read -p "Please enter an integer -> " int
check $int
doneAt the top of the function
check()
add this line, and try again:[[ $int == 'q' ]] && exit
This makes it possible to stop the script by pressing
q
(instead of terminating it withCtrl+c
). -
Testing files and their properties:
test-file.sh
#!/bin/bash
usage() {
cat <<EOF
Usage: $0 <path>
where <path> is a file or a directory.
EOF
exit 1
}
# evaluate the status of a file
test_file() {
local file=$1
if [[ ! -e $file ]]; then
echo "$file does not exist"
return 1
else
# test using the command 'test'
if test -f $file ; then
echo "$file is a regular file."
fi
# test using [...]
if [ -d $file ]; then
echo "$file is a directory."
fi
# test using [[...]]
if [[ -r $file ]]; then
echo "$file is readable."
fi
[[ -w $file ]] && echo "$file is writable."
[[ ! -x $file ]] \
|| echo "$file is executable/searchable."
fi
}
# [[ -z $1 ]] && usage
[[ -n $1 ]] || usage
# call the function
test_file $1./test-file.sh
./test-file.sh ~/.bashrc
./test-file.sh ~/.ssh
./test-file.sh ~/root
./test-file.sh test-integer-1.sh
./test-file.sh .
./test-file.sh test-file.sh
./test-file.sh foo.txt
touch foo.txt
./test-file.sh foo.txt
rm foo.txt
7. Case
-
Case with patters:
case.sh
#!/bin/bash
case "$1" in
[[:alpha:]])
echo "it is a single alphabetic character"
;;
[ABC][0-9])
echo "it is A, B, or C followed by a digit"
;;
???)
echo "it is three characters long"
;;
*.txt)
echo "it is a word ending in '.txt'"
;;
*)
echo "it is something else"
;;
esac./case.sh x
./case.sh B2
./case.sh foo.txt
./case.sh xyz
./case.sh ab
./case.sh x -
A menu driven system information program:
menu.sh
#!/bin/bash
# a menu driven system information program
main() {
while true; do
display_menu
read -p "Enter selection [A, B, C or Q] > "
echo
process_selection $REPLY
echo
read -p "Press <enter> to continue..."
done
}
display_menu() {
clear
cat <<_EOF_
A. Display System Information
B. Display Disk Space Utilization
C. Display Home Space Utilization
Q. Quit
_EOF_
}
process_selection() {
local selection=$1
case $selection in
q|Q) echo -e "Program terminated. \n"
exit
;;
a|A) echo -e "A. System Information \n"
echo Hostname: $HOSTNAME
uptime
;;
b|B) echo -e "B. Disk Space Utilization \n"
df -h .
;;
c|C) echo -e "C. Home Space Utilization \n"
display_home_space_utilization
;;
*) echo "Invalid entry: '$selection'"
;;
esac
}
display_home_space_utilization() {
if [[ "$(id -u)" -eq 0 ]]; then
echo "Home Space Utilization (All Users)"
du -sh /home/*
else
echo "Home Space Utilization ($USER)"
du -sh $HOME
fi
}
# call main
main "$@"