Lab 12 - Bash Lab
Operating Systems
Name
_________________________________
In this
lab, you will learn about the Bourne Again
or bash shell and how to use it. This lab is
based upon a CS2351 lab assignment from Oklahoma
State University. Shell scripts to be run in
the Bourne Again shell will be developed and shell
control statements used in the Bourne Again
shell will be introduced. Control statements covered
include: test, for, for in, if-then-else-fi,
if-then-elif-fi, while, until,
and case. Relational operators and expr
used in the Bourne Again shell are introduced.
Errors you may encounter are discussed. It is
recommended that you complete this lab using the
LittleFe cluster computer at littlefe2.nwmissouri.edu.
Submit your results from this lab to the dropbox for Lab 12.
|
The Bourne Again shell was written in 1989 by Brian Fox and extends upon many of the features of the Bourne shell. It has many similar features to the features of the Korn shell or the C shell. These features include a command history that may be accessed by pressing the up arrow to scroll through past commands, an autocomplete feature that will complete file or command names by pressing the tab key, or the command line editing like in the Korn shell. Aliases are also available. As the Bourne Again shell is You will not be able to use them while you are in the Bourne shell. This may be frustrating to you. One reason why you are looking at this shell, is that it is the main shell on many UNIX machines.
You can change to another shell on your machine at any time by just typing in the name of that shell at the prompt. Type in:
sh
What happened when you did this? ____________________________________________________
Your prompt should have changed. It should have something similar to # > or sh-3.2$. Usually it would be a $ sign but you changed from the bash shell to the Bourne shell. To return to the bash shell, type:
ctrl - d
or
exit
You will then be returned to the bash shell prompt. Note that you must be in the bash shell to log off.
First, let's make some script files in the home directory for the chmod command for you to use when you are in the Bourne Again shell. The chmod command allows you to change the permissions of a file. Note that there are three different levels of permissions - user, group, and world. With in each level, you may grant read, write, and/or execute permissions. Change to the home directory. Type in:
cd ~
Next, type in:
ls -al
What files did you see listed? ____________________________________________________________
All of these shell scripts will work in the Bourne Again shell because the start with the header #!/bin/bash. This is used to start a bash shell script. You are going to create a script to change the permissions of a file. First open nano type the following contents into the text editor and save the file with the name chb.
#!/bin/bash
# Change mode command
# This file will make a file executable
echo "Read in name of file to be made executable: "
read filename
chmod 700 $filename
echo "$filename is now executable: "
ls -l $filename
Make this file executable by typing chmod 700 chb.
Make another file called lsl. This file will allow you to print detailed contents of a directory without having to type the full command ls -al. Open nano, and type in the following then save the file as lsl.
#!/bin/bash
# This shell script will print all directory contents including
# permissions and size data.
ls -al
Make this file executable by using the chb file you just created by typing ./chb and recall that the first line starts with #!/bin/bash. bash stands for the Bourne Again shell. Note that the Bourne Again shell uses the echo statement to print data to the console. You will notice that many functions of this shell allow for programming similar to languages that you know like C, Python, Java, and Perl.
Shell scripts that you write in the Bourne Again shell should work automatically in other shells such as the Korn shell. However, this does not necessarily work in the reverse order. If a program was written in the Korn shell, it will not necessarily work in the Bourne Again or Bourne shell.
Ensure that you are in your home directory by typing cd ~
Now create a new directory by typing mkdir bashLab and change to that directory by typing cd bashLab You will create several files in this directory. Next, type the following command:
pwd
What was the output?______________________________________________________________
Flow of Control Structures
You will now be introduced to control structures available in bash. Some will look similar to those used in other programming languages such as Java. These are similar to if-then-else type of statements used in other programming languages.
Test Command
The first control statement is the test command. The test command evaluates an expression and returns a condition code indicating the expression is either true (= 0) or false (not = 0).
This command is used for branching. The if statement has the form:
if (test command)
then
commands
fi
The test command has many options that available including:
-f tests to see if filename listed is a file -d tests to see if filename listed is a directory -r tests to see if filename is a readable file -w tests to see if filename is writeable -x tests to see if filename is executable
Create a new shell script called sample1. Enter the following exactly as shown.
#!/bin/bash
if (test -f books)
then
ls
fi
The "then" must be on the second line. Notice that the control structure ends in "fi" or "if" spelled backwards. You will work with other bash control structures soon. Most end with the control structure name spelled backwards.
Assuming you are still in the bashLab directory, after you have completed sample1, use the chb shell script that you made earlier. At the prompt, type in:
../chb
You will be asked to "Read in name of file to be made executable". Type in:
sample1
You should then get a reply that "sample1" is now executable including output describing file permissions. The chb shell script can be used for other files that need to be made executable in this lab. Now type in:
./sample1
This should run the sample1 shell script. What answer did you get? _________________________________________________________________________________
Now create a file called books with the following data:
Hadoop Operations, Eric Sammer, 9781449327057
CUDA By Example: An Introduction to General-Purpose GPU Programming, Jason Sanders and Edward Kandrot, 9780131387683
Structured Parallel Programming: Patterns for Efficient Computation, Michael McCool James Reinders and Arch Robinson, 0124159931
Then, run sample1 again. What happened?
_________________________________________________________________________________
In the case of the single if statement, if the statement is true, the statement after the "then" is carried out. If it is not true, then nothing is done. Is the test condition true? ________________________
The two-branch if-statement is similar to the single-branch if-statement. Similar to the if then-clause, the else-clause must start on a new line. Create another script called sample2 with code exactly as shown below.
#!/bin/bash
if (test -d books)
then
echo "books is a directory file"
else
echo "books is a plain file with the "
echo "following access permissions:"
ls -l books
fi
Use the chb shell script to make this file executable and then type in:
./sample2
Is the test condition true ?___________________________
What is printed ? ________________________________________________________________________________
For loops
The bash for loop has the following format:
for loop-index
do
commands
done
The loop-index can automatically take on the value of each command line parameter, one at a time. It can then perform a series of commands involving each parameter.
Use the interactive cat command (cat >
<filename>) to create a file called wordsInBooks
that contains the following shell script. When you use the cat
command, and you are done entering information, press ctrl -
c. Be sure to press enter after entering the last
line.
#!/bin/bash
for i
do
grep -n $i books
done
Make this file executable by using chb.
The grep command is a search command that allows you to search for word or character matches in files. The shell script above will look for the list of arguments in the file books that are listed after the name of the shell script. In the example below, the wordsInBooks is the name of the shell script and Michael, Arch, and hal are arguments. You will search for these patterns in the file books.
Now, issue the command:
./wordsInBooks Michael Arch hal
What was the result? ________________________________________________________________
________________________________________________________________________________
________________________________________________________________________________
Next, issue the command:
./wordsInBooks to for
The grep command performs a global search to find matching patterns. It searches through each line in a file to find matches. This command can be time consuming if you have a large file. What was the result of the previous search? ______________________________________________________________________
_______________________________________________________________________________
Now try the search:
./wordsInBooks \&
This command searches for an ampersand. The backslash is required because & is a special character which when appended to a command, indicates that the command is to run as a background process thereby leaving the terminal free to issue other commands. Here we wanted to search for the &, hence the backslash. What was the result? _______________________________________________________________________________
For In
The for in control structure has the following format:
for loop-index in argument-list
do
<command list>
done
This structure assigns the value of the first argument in the argument list to the loop-index and executes the commands between the do and done statements. The do and done statements mark the beginning and end of the for loop. To see how this structure works, create the following script named names:
#!/bin/bash
for file in books*
do
echo "==============================="
echo "Sorted contents of $file"
echo "==============================="
sort -b $file
echo
done
Create three copies of the file books by issuing the following
commands.
cp books books1
cp books books2
cp books books3
Add different books to each of the files above.
Use the shell script chb to make names executable. Then execute names as follows.
*./names | more
Describe the output.
________________________________________________________________________________
________________________________________________________________________________
________________________________________________________________________________
Relational Operators used in the Bourne shell
Summary of Relational Operators ( see
http://www.tldp.org/LDP/abs/html/comparison-ops.html )
Operator Used to test: = equality of two strings != inequality of two strings -ne inequality of two integers -lt true if integer on left is less than integer on right -le true if integer on left is less than or equal to integer on right -gt true if integer on left is greater than integer on right -ge true if integer on left is greater than or equal to integer on right -f true if a file is a plain file -d true if a file is a directory -a logical and - true if expresssion on left and right are both true -o logical or - true if expresssion on left or right is true
If.. then .. else.. fi
The if-then-else-fi clause can be used to cause execution of statements to occur if the specified test proves false. The general format of the if-then-else-fi is:
if condition
then
commands
else
commands
fi
If the result of the condition is true, then the commands enclosed between the then and else are executed. Otherwise, the commands between the else and fi will be executed.
If .. then .. elif .. else ..fi
The elif statement combines the else and if statements and allows you to construct a nested set of if-then-elif-else-fi structures. The format for this is:
if condition
then
commands
elif
then
commands
else
commands
fi
As with else-if statements in Java, you may use as many elifs as you want. After the last elif, it is possible to use an else so a set of commands can be executed if none of the preceding expressions are true. Enter the following program called classification.
#!/bin/bash
#
# This program was written by: ( type your name here)
# This program will allow user to read in the number
# of hours a student has completed.
# It will then determine what classification the
# student is based on the hours completed.
#
#
echo "Enter the number of hours the student has completed: "
read number
if [ $number -ge 1 -a $number -le 27 ]
then
echo Class = Freshman
elif [ $number -gt 27 -a $number -le 60 ]
then
echo Class = Sophomore
elif [ $number -gt 60 -a $number -le 93 ]
then
echo Class = Junior
else
echo Class = Senior
fi
Be sure to make the program executable using chb.
Notice that you may enter your name in the comments section program.
Note: when you enter this program, be sure to leave a space after the open bracket ([) and before the close bracket (]). If you do not leave a space between the brackets and other characters, you will get an error message. Also note that the if statement ends with the fi statement. Run the program as follows:
./class2
At the prompt, enter a number. Execute the program
several times using different numbers that fit in the
different categories to test your shell control program.
While
In the while structure, as long as the test-command returns a true exit status, the structure executes the series of commands between do and done. Before each pass through the commands, the test-command is evaluated. When the exit status of the test-command is false, control is passed to the statement immediately following the done statement. The while construct appears as follows.
while test-command
do
commands
done
Create the following script called looping.
#!/bin/bash
count=1
while [ $count -le 10 ]
do
echo "$count"
count=`expr $count + 1`
done
Note: you need back quotes when you use the expr command in this example.
Describe the output of this script. _______________________________________________________________________________
Arithmetic operators - Expr command
Notice that the expr command was used in the while structure. It evaluates an expression. It evaluates character strings that represent either numeric or nonnumeric values. The expr command returns an exit status of 0 (zero) if the expression is neither a null string nor the number 0; it returns a status of 1 if the expression is null or 0; and it returns a status of 2 if the expression is invalid.
The following examples show commands that call expr to evaluate constants. You can also use expr to evaluate variables in a shell script. Type in the following examples and fill in the answers next to the expression:
expr 3 + 5 ___________ expr 3 "*" 9 ___________ expr 8+2 (no spaces between the 1 & 2) ___________ expr "9 * 14" ___________ count=103 ___________ expr $count + 9 ___________
Expr writes its results to the standard output. By using the backquote mechanism, you can assign expr's results to a shell variable:
result=`expr 1 + 2`
echo $result
These are just a few examples of how expr works. You can try other options or read more about it online.
Until
The until and while structures are very similar. They differ only in the evaluation of the test. The until continues to loop until the test-command returns a true exit status. The while structure loops while the test-command continues to return a true or nonerror condition. The until structure is shown below:
until test-command
do
commands
done
Create the following script. Call it numbers.
#!/bin/bash
read number
until [ $number -lt 0 ]
do
echo $number
number=`expr $number - 1`
done
Make this script executable and run it. You will see a
blank line. Type in 8 as the input
value. Describe the output of this script.
_______________________________________________________________________________
_______________________________________________________________________________
Case
The case structure provides a multiple branch decision mechanism. The case statement is similar to the switch statement in Java. The control path depends on a match between the test-string and one of the patterns. An example of this mechanism follows below.
case test-string in
pattern-1)
command list;;
pattern-2)
command list;;
pattern-N)
command list;;
esac
Note that the end of the case statement is esac.
Type in the following example using the nano editor. Name it choose:
#!/bin/bash
# This program was written by: (your name here)
echo "Enter 1, 2, 3, or 4: "
read number
case $number in
1)
date;;
2)
ls;;
3)
pwd;;
4)
who | wc -l;;
*)
echo You have entered an incorrect value;;
esac
After you have completed this script, make it executable and try it.
Error resolution in bash
If you are using an "if" statement in bash, you could get an error such as this:
<name of file>: syntax error at line7: `elif' unexpected
This likely means that you put the then statement on the same line with the "if" statement. You need to have the "then" statement on the next line as the first word on that line.
Another problem may be if you put a # (pound sign) in the first line without #!/bin/bash. UNIX will assume that you want to run the program in the default login shell, which may not be bash. If your defualt shell is not bash, you may get an error when the script is executed. An example would be if you used the # sign in the first line of the program, choose above, you may get an error message:
read:
Command not found.
number:
Undefined variable.
Other errors occur when you add a space between the "=" (equal) sign when you are assigning values to variables. You must not leave spaces on either side of an equal sign for assignment statements in bash.
In order to get log off the machine or close your terminal window, type in:
exit