Difference between revisions of "CSC231 Bash Tutorial 7"

From dftwiki3
Jump to: navigation, search
(Challenge #1:)
Line 270: Line 270:
 
Modify the previous script, noticing that "Smith", "Amherst", "Hampshire", and "MtHolyoke" all have suffix '''College''', and therefore one if statement with a then and else block can be used to set the suffix.  You will need other if statements for the towns.
 
Modify the previous script, noticing that "Smith", "Amherst", "Hampshire", and "MtHolyoke" all have suffix '''College''', and therefore one if statement with a then and else block can be used to set the suffix.  You will need other if statements for the towns.
 
<br />
 
<br />
 +
=Testing Files=
 +
<br />
 +
Because Bash interacts directly with Linux, it has a rich set of operators for testing files, and various file properties.  See the list of operators on this [http://tldp.org/LDP/abs/html/fto.html page] from '''tldp.org''' for a list of all of them.
 +
<br />
 +
Let's try one, and list all the executable files in your directory.  The operator '''-x''' operator, if applied to a file, will return True if the file is executable (the files generated by '''ld''' and the files you applied '''chmod -x''' to).
 +
<br />
 +
You can probably figure out how to write this script, but here it is:
 +
<br />
 +
::<source lang="bash">
 +
#! /bin/bash
 +
# if4.sh
 +
# prints executable files only
 +
#
 +
 +
for file in * ; do
 +
  if [ -x $file ] ; then
 +
      echo $file
 +
  fi
 +
done
  
 +
</source>
 
<br />
 
<br />
 +
* Test it in your home directory. 
 +
* Verify that it is listing all your executables.
 +
<br />
 +
{| style="width:100%; background:limegreen"
 +
|-
 +
|
 +
 +
==Challenge #3:==
 +
|}
 +
[[Image:QuestionMark3.jpg|right|120px]]
 +
<br />
 +
Given the name of a file, say in variable $file, Bash can extract its extension with this (strange looking) expression: <tt>${file##*.}</tt>
 +
<br />
 +
* See how it works by trying this script in your main directory:
 +
<br />
 +
::<source lang="bash">
 +
#! /bin/bash
 +
# challenge3_prep.sh
 +
# D. Thiebaut
 +
# displays the files and their extension in the current directory
 +
 +
# for all files in the current directory
 +
for file in * ; do
 +
    # get its extension
 +
    extension=${file##*.}
 +
    # print extension and file-name
 +
    echo "$extension -- $file"
 +
done
 +
</source>
 +
* Your challenge: write a script that will list all the files in your directory, divided into 3 sections: asm files,
 +
object files (with a .o extension), and scripts (with a .sh extension).  Below is the output of the solution program
 +
running in my handout directory:
 +
<br />
 +
 +
--- o ---
 +
GameOfLife.o
 +
 +
--- asm ---
 +
231Lib.asm
 +
addmovExample.asm
 +
fib.asm 
 +
GameOfLife.asm
 +
GameOfLifeDT.asm
 +
mystery.asm
 +
newFile.asm
 +
printRegsExample.asm
 +
prog1.asm
 +
prog2.asm
 +
prog3.asm
 +
prog4.asm
 +
quiz1.asm
 +
skel.asm
 +
teller.asm
 +
test_skel.asm
 +
 +
--- sh ---
 +
dateTag.sh
 +
randomWord2.sh
 +
randomWord3.sh
 +
randomWord.sh
 +
runNQueens.sh
 +
runTeller.sh
 +
script1.sh
 +
script2.sh
 +
script3.sh
 +
teller.sh
 +
test1.sh
 +
 +
<!-- ================================================================== -->
 
<showafterdate after="20170331 11:45" before="20170601 00:00">
 
<showafterdate after="20170331 11:45" before="20170601 00:00">
 
=Solutions to Challenges=
 
=Solutions to Challenges=
Line 339: Line 428:
 
</source>
 
</source>
 
<br />
 
<br />
 +
 
</showafterdate>
 
</showafterdate>
 
<br />
 
<br />

Revision as of 06:58, 31 March 2017

--D. Thiebaut (talk) 06:15, 31 March 2017 (EDT)




This lab deals with if-statements in bash scripts. If statements in Bash work the same way they work in Python and Java: if somebooleanexpression then dothis else dothat.



Reference



Backing up your files


Just in case you mess up and erase files in your account by mistake, you will make an archive of all your files and save it in your instructor's account:

cd
tar -czvf backup2.tgz *
rsubmit backup backup2.tgz

That's it! An archive of all your file should now be saved and available in case of accident!

The Bash If-Statement


The Bash if-statement looks like this:

 
if  [  someExpression ] ; then
   bash statement
   bash statement
else
   bash statement
   bash statement
fi


Of course, there can be as many bash statements inside the then or else block, including for loops, or other if statements.

  • Make sure to end the if statement with a fi keyword.
  • The else block is not necessary and can be omitted if the logic doesn't call for it.

Testing Numerical Values


  • Create this bash script, make it executable, and run it a couple times:


#! /bin/bash
# if0.sh

#--- get input from user ---
echo -n  "Please enter an integer between 1 and 10 (included): "
read guess

#--- display number back ---
echo "You have entered $guess"


  • Let's modify it and test the value the user enters:


#! /bin/bash
# if0.sh

#--- get input from user ---
echo -n  "Please enter an integer between 1 and 10 (included): "
read guess

#--- test if number entered is below or above 5 ---
if [ "$guess" -le "5" ] ; then
   echo "You aim low!"
else
   echo "Above average!" 
fi


  • Make sure you have spaces around the brackets and around the operator inside the brackets!
  • The "-le" operator stands for "less than or equal to." Bash supports the following operators for comparing numbers:
  • -le    (less than or equal to)
  • -lt    (less than )
  • -ge    (greater than or equal to)
  • -gt    (greater than)
  • -eq    (equal to)
  • -ne    (not equal to)


Nested If-Statements


  • Of course, if Bash supports if statements, it will support nested if statements.
  • Try this new version of the script:


#! /bin/bash
# if2.sh

#--- get user input ---
echo -n  "Please enter an integer between 1 and 10 (included): "
read guess

#--- test if below or above 5 ---
if [ "$guess" -le "5" ] ; then

   #--- compute even/odd property of guess
   x=$( expr $guess % 2 )

   #--- test if guess is odd or even ---
   if [  $x -eq 0 ] ; then
       echo "low even number"
   else
       echo "low odd number"
   fi

else
   echo "Above average!" 
fi




Challenge #1:

QuestionMark1.jpg


Write a script that prompts the user for an integer number between 0 and 100 (inclusive) and outputs a letter grade, using Moodle's default grade table:

Moodle Table
Range Letter Grade

100.00 -93.00

A

92.99 - 90.00

A-

89.99 - 87.00

B+

86.99 - 83.00

B

82.99 - 80.00

B-

79.99 - 77.00

C+

76.99 - 73.00

C

72.99 - 70.00

C-

69.99 - 67.00

D+

66.99 - 60.00

D

59.99 - 0.00

F


  • Note 1: You do not have to worry about real numbers here. You can do all your testing with integers.
  • Note 2: Feel free to test just the top 3 ranges of numbers. If you can do it for 3, you can do it for the full list!


Testing and Comparing Strings


Bash uses different operators for strings: = for equality, and != for inequality. Here is an example:

#! /bin/bash
# if3.sh

for name in "Smith" "Hampshire" "Umass"  "Amherst" "MtHolyoke" ; do

   if [ "$name" == "Smith" ]; then
       town="Northampton"
       suffix="College"
   fi

   if [ "$name" == "Amherst" ]; then
       town="Amherst"
       suffix="College"
   fi
   if [ "$name" == "Umass" ]; then
       town="Amherst"
       suffix=""
       name="University of Mass."
   fi
   if [ "$name" == "MtHolyoke" ]; then
       town="South Hadley"
       suffix="College"
   fi
   if [ "$name" == "Hampshire" ]; then
       town="Amherst"
       suffix="College"
   fi

   echo "$name $suffix, $town, Massachusetts"

done


  • Try it!
  • You will have noticed that the then-blocks for "Amherst" and "Hampshire" are the same, so we could simplify our code by using a logical OR operator for "Amherst" and "Hampshire". The syntax for logical operators in Bash is a bit weird, though... logical:


if [ "$name" == "Amherst" ] || [ "$name" == "Hampshire" ]; then
       town="Amherst"
       suffix="College"
fi


  • The OR operator is || and the AND operator is &&.



Challenge #2:

QuestionMark2.jpg


Modify the previous script, noticing that "Smith", "Amherst", "Hampshire", and "MtHolyoke" all have suffix College, and therefore one if statement with a then and else block can be used to set the suffix. You will need other if statements for the towns.

Testing Files


Because Bash interacts directly with Linux, it has a rich set of operators for testing files, and various file properties. See the list of operators on this page from tldp.org for a list of all of them.
Let's try one, and list all the executable files in your directory. The operator -x operator, if applied to a file, will return True if the file is executable (the files generated by ld and the files you applied chmod -x to).
You can probably figure out how to write this script, but here it is:

#! /bin/bash
# if4.sh
# prints executable files only
#

for file in * ; do
   if [ -x $file ] ; then
      echo $file
   fi
done


  • Test it in your home directory.
  • Verify that it is listing all your executables.


Challenge #3:

QuestionMark3.jpg


Given the name of a file, say in variable $file, Bash can extract its extension with this (strange looking) expression: ${file##*.}

  • See how it works by trying this script in your main directory:


#! /bin/bash
# challenge3_prep.sh
# D. Thiebaut
# displays the files and their extension in the current directory

# for all files in the current directory
for file in * ; do
    # get its extension
    extension=${file##*.}
    # print extension and file-name
    echo "$extension -- $file"
done
  • Your challenge: write a script that will list all the files in your directory, divided into 3 sections: asm files,

object files (with a .o extension), and scripts (with a .sh extension). Below is the output of the solution program running in my handout directory:

--- o ---
GameOfLife.o

--- asm ---
231Lib.asm
addmovExample.asm
fib.asm  
GameOfLife.asm 
GameOfLifeDT.asm
mystery.asm
newFile.asm
printRegsExample.asm
prog1.asm
prog2.asm
prog3.asm
prog4.asm
quiz1.asm
skel.asm
teller.asm
test_skel.asm

--- sh ---
dateTag.sh
randomWord2.sh
randomWord3.sh
randomWord.sh
runNQueens.sh
runTeller.sh
script1.sh
script2.sh
script3.sh
teller.sh
test1.sh 

<showafterdate after="20170331 11:45" before="20170601 00:00">

Solutions to Challenges


Challenge 1


#! /bin/bash
# challenge1.sh
# D. Thiebaut

# get integer grade
echo -n "Enter the grade (0-100): "
read grade

if [ "$grade" -gt "93" ]; then
   echo "A"
else
   if [ "$grade" -gt "90" ]; then
      echo "A-"
   else
      if [ "$grade" -gt "87" ]; then
         echo "B+"
      else
         if [ "$grade" -gt "83" ]; then
            echo "B"
         else
            echo "Grade lower than B"
         fi
      fi
   fi
fi
Challenge 2


#! /bin/bash
# Challenge2.sh
# D. Thiebaut

# displays the name of the 5 colleges and where they are located
for name in "Smith" "Hampshire" "Umass"  "Amherst" "MtHolyoke" ; do

   if [ "$name" == "Amherst" ] || [ "$name" == "Hampshire" ] || [ "$name" == "Umass" ]; then
       town="Amherst"
   else
       if [ "$name" == "Smith" ]; then
          town="Northampton"
       else
          town="South Hadley"
       fi
   fi

   if [ "$name" == "Smith" ] ||  [ "$name" == "Amherst" ] || [ "$name" == "Hampshire" ] \
      || [ "$name" == "MtHolyoke" ] ; then
       suffix="College"
   else
       name="University of Mass."
       suffix=""
   fi

   echo "$name $suffix, $town, Massachusetts"

done


</showafterdate>