In the print dialog, choose "Save as PDF" as the destination.
Operating Systems 1, Lab 11
Write your first scripts: run them, store values, read input, calculate, and make decisions.
./script.sh and bash script.sh#!/bin/bash, chmod 755 and why ./ is needed$( ) and the arguments $1, $#, $@read, read -p, read -s and from STDINlet, expr and $(( ))if, elif, else, the test operators, &&, || and caseFirst Scripts
A plain text file of commands
.sh (myscript.sh); Linux itself does not need the extensionProgram
instructions stored on disk
Process
a running copy in RAM
Your script
runs in a new bash process
cp means two cp processesexport)#!/bin/bash
# A sample Bash script
echo Hello World!#echo prints a message, the same as at the promptA new file has no execute permission. Predict what each command prints.
$ ./myscript.sh
$ ls -l myscript.sh
$ chmod 755 myscript.sh
$ ls -l myscript.sh
$ ./myscript.sh$ ./myscript.sh
bash: ./myscript.sh: Permission denied
$ ls -l myscript.sh
-rw-r--r-- 1 student student 53 Sep 25 12:10 myscript.sh
$ chmod 755 myscript.sh
$ ls -l myscript.sh
-rwxr-xr-x 1 student student 53 Sep 25 12:10 myscript.sh
$ ./myscript.sh
Hello World!Bash looks for a command only in the directories listed in $PATH
$ myscript.sh
bash: myscript.sh: command not found
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
$ /home/student/lab11/myscript.sh
Hello World!:; the current directory is not one of them./myscript.sh (relative) or the full absolute pathls in some folder is never run by accidentbadbang.sh starts with #!/bin/bas, one letter missing. Predict both runs.
#!/bin/bas
# the interpreter path is misspelled
echo Hello World!$ ./badbang.sh
$ bash badbang.sh$ ./badbang.sh
bash: ./badbang.sh: cannot execute: required file not found
$ bash badbang.sh
Hello World!Storing Values
Temporary stores of information
name=value, no $, and no spaces around =$name; before running a line, bash replaces each variable with its valuemyvar and MYVAR are two variables$ myvar = Hello
$ myvar=Hello
$ echo $myvar
$ echo $MYVAR$ myvar = Hello
bash: myvar: command not found
$ myvar=Hello
$ echo $myvar
Hello
$ echo $MYVAR
Predict the output of ./simplevariables.sh
#!/bin/bash
# A simple variable example
myvariable=Hello
anothervar=Linux
echo $myvariable $anothervar
echo
sampledir=/etc/apt
ls $sampledirecho with no arguments prints an empty linels $sampledir becomes ls /etc/apt before it runs$ ./simplevariables.sh
Hello Linux
apt.conf.d auth.conf.d keyrings preferences.d sources.list sources.list.d trusted.gpg.dBash splits words on spaces; quotes make one item. Predict each line.
$ myvar=Hello World
$ myvar='Hello World'
$ echo $myvar
$ newvar="More $myvar"
$ echo $newvar
$ newvar='More $myvar'
$ echo $newvar$ myvar=Hello World
bash: World: command not found
$ myvar='Hello World'
$ echo $myvar
Hello World
$ newvar="More $myvar"
$ echo $newvar
More Hello World
$ newvar='More $myvar'
$ echo $newvar
More $myvarSave the output of a command in a variable
$ myvar=$( ls /etc | wc -l )
$ echo There are $myvar entries in the directory /etc
There are 74 entries in the directory /etc
$ ls /etc/apt
apt.conf.d auth.conf.d keyrings preferences.d sources.list sources.list.d trusted.gpg.d
$ files=$( ls /etc/apt )
$ echo $files
apt.conf.d auth.conf.d keyrings preferences.d sources.list sources.list.d trusted.gpg.dls -l /etc gives ls two arguments; a script gets its arguments the same way
#!/bin/bash
# A simple copy script
cp $1 $2
# Let's verify the copy worked
echo Details for $2
ls -lh $2$ ./mycopy.sh salesdata.txt backup.txt
Details for backup.txt
-rw-r--r-- 1 student student 123 Sep 25 12:11 backup.txtSet by the system for every script
| Variable | Holds |
|---|---|
$0 | the name of the script |
$1 to $9 | the first nine command line arguments |
$# | how many arguments were passed |
$@ | all the arguments |
$? | the exit status of the last command |
Predict ./args.sh red green blue
#!/bin/bash
# special variables set by the system
echo "Script name: $0"
echo "Number of arguments: $#"
echo "All arguments: $@"
echo "Second argument: $2"
echo "User: $USER, host: $HOSTNAME"
echo "This is line $LINENO"$ ./args.sh red green blue
Script name: ./args.sh
Number of arguments: 3
All arguments: red green blue
Second argument: green
User: student, host: ubuntu-lab
This is line 8script1.sh runs script2.sh. Predict the three lines.
#!/bin/bash
# demonstrate variable scope 1.
var1=blah
var2=foo
# Let's verify their current value
echo $0 :: var1 : $var1, var2 : $var2
export var1
./script2.sh
# Let's see what they are now
echo $0 :: var1 : $var1, var2 : $var2#!/bin/bash
# demonstrate variable scope 2
# Let's verify their current value
echo $0 :: var1 : $var1, var2 : $var2
# Let's change their values
var1=flop
var2=bleh$ ./script1.sh
./script1.sh :: var1 : blah, var2 : foo
./script2.sh :: var1 : blah, var2 :
./script1.sh :: var1 : blah, var2 : fooReading Data
Let the user supply the data
#!/bin/bash
# Ask the user for their city
echo Hello, which city are you from?
read varcity
echo It\'s nice to meet someone from $varcity$ ./introduction.sh
Hello, which city are you from?
Mansoura
It's nice to meet someone from Mansoura#!/bin/bash
# Ask the user for login details
read -p 'Username: ' uservar
read -sp 'Password: ' passvar
echo
echo Thank you $uservar, we now have your login details$ ./login.sh
Username: student
Password:
Thank you student, we now have your login detailsPredict the output when the user types four cars, then only two.
#!/bin/bash
# Demonstrate how read actually works
echo What cars do you like?
read car1 car2 car3
echo Your first car was: $car1
echo Your second car was: $car2
echo Your third car was: $car3$ ./cars.sh
What cars do you like?
Jaguar Maserati Bentley Lotus
Your first car was: Jaguar
Your second car was: Maserati
Your third car was: Bentley Lotus
$ ./cars.sh
What cars do you like?
Jaguar Maserati
Your first car was: Jaguar
Your second car was: Maserati
Your third car was:#!/bin/bash
# A basic summary of my sales report
echo Here is a summary of the sales data:
echo ====================================
echo
cat /dev/stdin | cut -d' ' -f 2,3 | sort$ cat salesdata.txt | ./summary.sh
Here is a summary of the sales data:
====================================
apples 20
oranges 5
peaches 7
watermelons 12| Method | Best when |
|---|---|
| Command line arguments | most scripts: kept in the history, easy for other scripts to call |
read | the data must not stay in the history, such as a password |
| STDIN | the script is a filter in a pipeline |
Whole Numbers
It all adds up
let saves the result in a variable. Predict ./let_example.sh 15
#!/bin/bash
# Basic arithmetic using let
let a=5+4
echo $a
let "a = 5 + 4"
echo $a
let a++
echo $a
let "a = 4 * 5"
echo $a
let "a = $1 + 30"
echo $a$ ./let_example.sh 15
9
9
10
20
45expr prints the result. Predict ./expr_example.sh 12
#!/bin/bash
# Basic arithmetic using expr
expr 5 + 4
expr "5 + 4"
expr 5+4
expr 5 \* $1
expr 11 % 2
a=$( expr 10 - 3 )
echo $a$ ./expr_example.sh 12
9
5 + 4
5+4
60
1
7$ expr 5 * 4
expr: syntax error: unexpected argument ‘args.sh’
$ expr 5 \* 4
20The recommended way. Predict the seven numbers.
#!/bin/bash
# Basic arithmetic using double parentheses
a=$(( 4 + 5 )); echo $a
a=$((3+5)); echo $a
b=$(( a + 3 )); echo $b
b=$(( $a + 4 )); echo $b
(( b++ )); echo $b
(( b += 3 )); echo $b
a=$(( 4 * 5 )); echo $a$ ./expansion2.sh
9
8
11
12
13
16
20| Operator | Meaning |
|---|---|
+ - * / | add, subtract, multiply, divide |
% | remainder after division |
var++ var-- | add 1, subtract 1 |
b += 3 | short for b = b + 3 |
${#var} | length of the value (characters) |
$ echo $(( 7 / 2 )) $(( 7 % 2 ))
3 1
$ echo $(( 2 * 3 + 4 )) $(( 2 * (3 + 4) ))
10 14
$ a='Hello World'
$ echo ${#a}
11Choosing a Path
Decisions, decisions
#!/bin/bash
# Basic if statement
if [ $1 -gt 100 ]
then
echo Hey that\'s a large number.
pwd
fi
date$ ./if_example.sh 15
Fri Sep 25 12:13:04 PM UTC 2026
$ ./if_example.sh 150
Hey that's a large number.
/home/student/lab11
Fri Sep 25 12:13:05 PM UTC 2026[ is another name for test, so it needs spaces like any command
$ [5 -lt 12]
bash: [5: command not found
$ [ 5 -lt 12]
bash: [: missing `]'
$ [ 5 -lt 12 ]
$ echo $?
0Each example below is true (we checked every one with echo $?)
| Operator | True when | Example |
|---|---|---|
-eq | numerically equal | [ 5 -eq 5 ] |
-gt | greater than | [ 9 -gt 5 ] |
-lt | less than | [ 3 -lt 8 ] |
-ge | greater than or equal | [ 7 -ge 7 ] |
-le | less than or equal | [ 4 -le 6 ] |
| Test | True when |
|---|---|
S1 = S2 | the strings are equal |
S1 != S2 | the strings are not equal |
-n S | S is not empty |
-z S | S is empty |
| Test | True when the path |
|---|---|
-e P | exists |
-d P | exists and is a directory |
-s P | exists and is not empty |
-w P | exists and is writable |
-x P | exists and is executable |
test prints nothing; its exit status answers: 0 true, 1 false. Predict each $?.
$ test 001 = 1
$ test 001 -eq 1
$ touch myfile; test -s myfile
$ ls /etc > myfile; test -s myfile$ test 001 = 1
$ echo $?
1
$ test 001 -eq 1
$ echo $?
0$ touch myfile
$ test -s myfile
$ echo $?
1
$ ls /etc > myfile
$ test -s myfile
$ echo $?
0Predict the three runs below.
#!/bin/bash
# elif statements
if [ $1 -ge 18 ]
then
echo You may go to the party.
elif [ $2 == 'yes' ]
then
echo You may go to the party but be back before midnight.
else
echo You may not go to the party.
fi$ ./if_elif.sh 20 no
$ ./if_elif.sh 16 yes
$ ./if_elif.sh 16 no$ ./if_elif.sh 20 no
You may go to the party.
$ ./if_elif.sh 16 yes
You may go to the party but be back before midnight.
$ ./if_elif.sh 16 no
You may not go to the party.Predict the output for 150, 151 and 50.
#!/bin/bash
# Nested if statements
if [ $1 -gt 100 ]
then
echo Hey that\'s a large number.
if (( $1 % 2 == 0 ))
then
echo And is also an even number.
fi
fi$ ./nested_if.sh 150
Hey that's a large number.
And is also an even number.
$ ./nested_if.sh 151
Hey that's a large number.
$ ./nested_if.sh 50Predict the output for code and age 1100 5, 1100 45, 1200 45
#!/bin/bash
echo "Enter your code"
read code
echo "Enter your age"
read age
if [[ $age -ge 18 && $code -eq '1100' ]]
then
echo "You are eligible to see the movie"
else
echo "You are not eligible to see the movie"
fi| code | age | Output |
|---|---|---|
| 1100 | 5 | You are not eligible to see the movie |
| 1100 | 45 | You are eligible to see the movie |
| 1200 | 45 | You are not eligible to see the movie |
#!/bin/bash
# case example
case $1 in
start) echo starting ;;
stop) echo stopping ;;
restart) echo restarting ;;
*) echo don\'t know ;;
esac$ ./case2.sh start
starting
$ ./case2.sh stop
stopping
$ ./case2.sh restart
restarting
$ ./case2.sh pause
don't knowYour Turn
About 30 minutes: predict on paper, then write and run your own scripts
About 5 minutes
#!/bin/bash
a=7
b=3
echo '$a + $b'
echo "$a + $b"
echo $(( a + b )) $(( a / b )) $(( a % b ))
expr $a \* $b
let "c = a * b - 1"
echo $c ${#c}$ ./practice1.sh
$a + $b
7 + 3
10 2 1
21
20 2$a + $b stays literal7 / 3 is 2, 7 % 3 is 1expr needs \*; c = 7 * 3 - 1 = 20, which has 2 charactersAbout 5 minutes
test 5 -lt 12test abc = ABCtest 010 -eq 10test 010 = 10test -z ""test -e nofile.txt (no such file)$ test 5 -lt 12
$ echo $?
0
$ test abc = ABC
$ echo $?
1
$ test 010 -eq 10
$ echo $?
0$ test 010 = 10
$ echo $?
1
$ test -z ""
$ echo $?
0
$ test -e nofile.txt
$ echo $?
1About 8 minutes
larger.sh; it takes two numbers as command line argumentsThe larger number is N with the larger oneBoth numbers are N./larger.sh 17 42, 42 17 and 9 9#!/bin/bash
# print the larger of two numbers
if [ $1 -gt $2 ]
then
echo "The larger number is $1"
elif [ $1 -lt $2 ]
then
echo "The larger number is $2"
else
echo "Both numbers are $1"
fi$ ./larger.sh 17 42
The larger number is 42
$ ./larger.sh 42 17
The larger number is 42
$ ./larger.sh 9 9
Both numbers are 9About 10 minutes
bill.sh; ask with read -p for the price of one item and the quantityTotal: T with $(( ))500 or more, print a 10% discount (total / 10) and the amount to payNo discount, to pay: T120 x 3 and with 200 x 3#!/bin/bash
# a shop bill with a discount
read -p "Price of one item: " price
read -p "Quantity: " qty
total=$(( price * qty ))
echo "Total: $total"
if [ $total -ge 500 ]
then
discount=$(( total / 10 ))
echo "Discount: $discount"
echo "To pay: $(( total - discount ))"
else
echo "No discount, to pay: $total"
fi$ ./bill.sh
Price of one item: 120
Quantity: 3
Total: 360
No discount, to pay: 360
$ ./bill.sh
Price of one item: 200
Quantity: 3
Total: 600
Discount: 60
To pay: 540#!/bin/bash first, chmod 755, then ./script.shname=value with no spaces; $name reads it; double quotes substitute, single quotes do not$1 $# $@ from the command line, read -p / read -s from the keyboard, /dev/stdin from a pipe$(( )) is the preferred arithmetic; results are whole numbers[ ] is test: exit status 0 is true; -eq compares numbers, = compares textif / elif / else / fi, joined with && and ||, or case for patternsMahmoud Abas|Bash Scripting, Part 1: Variables, Input, Arithmetic and If