Introduction to Shell Scripting
Bash system
- Navigate to a terminal to with a bash shell
- Make a new directory with the
mkdir
command calledShell
, and the change to that directory$ cd ~/path/to/Shell
- Make new directory,
$ mkdir scripting
and again change directory toscripting
Task 1. #!
Shebang/hashbang
-
Create a new file called
script.sh
-
Then edit the file
-
Reproduce the following...
-
Write out
ctrl+x
-
Modify the file's mode bits so that it becomes an executable
-
performing
ls -l
either side of thechmod
command shows the information about the file such as its mode bits.-
Before:
-
After:
-
-
-
Now you are going to run the script two ways.
-
first way is to call the script via bash directly:
-
Ouput:
-
-
Second way is to run the script as an executable
-
Ouput:
-
-
Lets modifiy the script so that the
#! /usr/bin/env wc
-
write out
ctrl+x
-
What will running the script do?
-
Run it and find out.
-
Task 2. Variables
-
create a new file and call it
int-or-string.sh
-
Reproduce the following:
-
You can change the mode bits again if you like or run with just
bash
.-
bash int-or-string.sh
-
or
chmod +x int-or-string.sh
,./int-or-string.sh
-
Output:
-
This behaved as expected, using arthemtric expansion
$((...))
to increment variableA
by 1.
-
-
Modify the script to include, pay attention to the comments.
B=${A/23/BB} # Substitute "BB" for "23". # This transforms $b into a string. echo "B = ${B}" # B = BB35 declare -i B # Declaring it an integer doesn't help. echo "B = ${B}" # B = BB35 B=$(( ${B} + 1 )) # BB35 + 1 echo "B = $B" # B = 1 echo # Bash sets the "integer value" of a string to 0. C=BB34 echo "C = $C" # C = BB34 D=${C/BB/23} # Substitute "23" for "BB". # This makes $D an integer. echo "D = ${D}" # D = 2334 D=$(( ${D} + 1 )) # 2334 + 1 echo "D = ${D}" # D = 2335 echo
-
Output:
-
-
Still on Variables... create a new script called
my-name-is.sh
-
reproduce the following code, like from the lecture slide.
-
again note the Uppercase standard for nameing convention here.
-
Notice how not all variables values are explicitly declared as string
""
. You only need to do this if there are spaces between letters/words. -
run the command.
-
Output:
- But hold on... what about
NAME=${1:-"Slim Shady"}
- Well this special operation allows default values to be assigned to the variable if something is
null
such as1
is the positional number for a parameter coming into the script when it is called from the CLIm if this isnull
then setNAME=Slim Shady
.
- Well this special operation allows default values to be assigned to the variable if something is
- But hold on... what about
-
Try calling the script but this time provide your first name, or mulitple names encapsulated with
"name name name"
-
Output:
-
Task 3. Loops
-
Create a new script called
forloops.sh
-
Reproduce the following code, pay attention to the comments.
#! /usr/bin/env bash DIR="task5" # if directory (-d) does not exist (!), then create it if [[ ! -d ${DIR} ]]; then mkdir ${DIR} && echo "${DIR} created" # if successful printout created fi # a becomes 1 then 2, and 3 and this is appended to the word foo_ to # create files in the directory that was created. for a in 1 2 3 ; do touch ${DIR}/foo_$a done
-
Run this command, and see if you get a new directory filled with files.
-
You can check by running the ls & wc -l command in terminal:
-
Lets modify the script again
#! /usr/bin/env bash DIR="task5" # if directory (-d) does not exist (!), then create it if [[ ! -d ${DIR} ]]; then mkdir ${DIR} && echo "${DIR} created" # if successful printout created fi # counts the number of files in the directory # you can run commands and save the outputs to variables using $(...) COUNT=$( ls ${DIR} | wc -l ) # arthimetic operations can be formed using $((...)) BOUND=$(( ${COUNT}+5 )) # using the seq command you can create sequence from one number to # another... seq a b, 1 to 10 for example. # this way we can create a new file proceeding the last file in the dir for a in $( seq ${COUNT} ${BOUND} ) ; do touch ${DIR}/foo_$a done
-
Run the command and perform the command
ls task5/ | wc -l
to see if the files have been created. Rinse and repeat a few times to see if it works. -
Now create a
whileloop.sh
file
- Run this and see the output in the terminal,
- experiment with:
-lt
less than-le
less than equal to-eq
equal to-ge
greater than equal to-gt
greater than
- experiment with:
Task 4. Special parameters and conditions
So now you are going to understand in more detail how parameters work.
-
Create a new script called
parameters.sh
-
edit the script to look like this:
#! /usr/bin/env bash while getopts u:a:f: flag do case "${flag}" in u) username=${OPTARG};; a) age=${OPTARG};; f) fullname=${OPTARG};; esac done echo "Username: $username" echo "Age: $age" echo "Full Name: $fullname"
-
Run the script by only supplying your username, age and full name.
-
What happened?
-
Try again this time provide your a
-u
then the username. -
Repeat but provide all options
-u
,-a
, and-f
-
-
Modify the code again, so that parameters can be precheck before coming to
getopts
#! /usr/bin/env bash if [[ $# -gt 6 ]];then echo -e "Too many arguments supplied:\n$#" exit 1 elif [[ $# == 0 ]]; then echo -e "Not enough arguments supplied:\n$#" exit 1 fi while getopts u:a:f: flag do case "${flag}" in u) username=${OPTARG};; a) age=${OPTARG};; f) fullname=${OPTARG};; esac done echo "Username: $username" "Age: $age" "Full Name: $fullname"
-
Try to run the script with no parameters, what happens?
-
Try to run the script with more than 6 parameters, what happens?
-
What about providing a flag that is not accounted for?
Task 5. Reading from stdin
Here you are replicating what was in the lecture using the read
command to caputer user input.
-
create a new script called
userinput.sh
-
reproduce the following code, pay attention to the comments:
#! /usr/bin/env bash echo -n "Enter your name:" read NAME # stores user's input echo "Your name is:" ${NAME} # prints user's input # prompt with and stores user's input read -p "Enter your name: " NAME echo Your name is ${NAME}. # prompt with suppressed feature enable so user input is hidden read -t 5 -p "Enter your password: "$'\n' -s PASSWORD echo ${PASSWORD} # though it is stored as plain text here... read -a WORDS <<< "Hello world!" # stores an array '-a` echo ${WORDS[0]} # accessing the arrays indicies echo ${WORDS[1]} echo ${WORDS[@]} # access the entire array echo ${#WORDS[1]} # get length of the index echo ${#WORDS[@]} # get lenght of array
-
Run the code, what output/experience do you get?