CSC 161 Schedule Readings Labs & Projects Homework Deadlines Resources

Bash Shell Scripting

Summary: In this laboratory you will gain experience writing Bash scripts.

Contents

  1. Getting Started
  2. Control Structures: if
  3. Control Structures: while
  4. Getting User Input
  5. Control Structures: for
  6. Some Useful Scripts

Part A: Getting Started

  1. Write a bash script called greeting.sh that prints a greeting to the user.

    1. Start with the greeting "Good morning" or something similar.

      Reminders as you get started:

      • You will need to insert the proper incantation on the first line of the script.
      • File permissions must be set to allow execution.
      • Commands in the script file do not need to end with semi-colons. (They are bash commands, not C statements.)
    2. Modify your script greeting.sh so that it
      • greets the user by (user)name,
      • prints the current date, and
      • prints a list of users currently logged onto the computer.
      For example, your output might look similar to the following:
      ./greeting.sh
      Good morning, mcoahran.
      Date is Sun Apr 20 12:22:47 CDT 2008
      Users on Leah:
      mcoahran :0           2008-04-20 11:45
      mcoahran pts/0        2008-04-20 11:45 (:0.0)
      mcoahran pts/1        2008-04-20 11:49 (:0.0)
    3. Be sure to include comments to your script! Comments in bash scripts begin with #, except on the very first line.

Part B: Control Structures: if

As you work through the next parts of this laboratory exercise, you will probably need to use variables and arithmetic comparisons.

  1. Modify your script greeting.sh from Step 1 to present a different greeting based on the time of day. For example, your greeting could be "good morning", "good afternoon", "good evening", or "YOU SHOULD BE SLEEPING!" based on the current hour. Note that the following command can be used to return the (24-hour) hour of the current time:

    date +%k

Part C: Control Structures: while

  1. Using a while loop, write a script called countdown.sh that prints output similar to the following:

    10
    9
    8
    7
    6
    5
    4
    3
    2
    1
    GO!

    Don't forget that bash uses the same arithmetic operators as C, but arithmetic expressions need to be wrapped in double-parentheses.

Part D: Getting User Input

  1. Modify countdown.sh from Step 3 such that it prompts user for a starting value, and counts down from there.
  2. Write a script called countdown2.sh that accepts the initial value as a command-line argument.
    1. Initially, the command and its output might look like the following.
      ./countdown2 12
      12
      11
      10
      9
      8
      7
      6
      5
      4
      3
      2
      1
      GO!
    2. Expand the script countdown2.sh to check for correct usage. The script should print a usage message and exit if it does not receive exactly one argument. An example session might look like this:
      ./countdown2.sh
      Usage: countdown2.sh initial-value
      Be sure you do not hardcode the name of the script in your code! Also note that you can exit a bash script with:
      exit returnvalue

Part E: Control Structures: for

  1. Consider the following bash commands. Predict what it will do, and then copy it and run it in the terminal to confirm your prediction.
    for var in 1 2 3 4 5
    do
       echo $var chimpanzee...
    done
    echo DONE!
  2. Recall that your bash script is run by the very same bash that responds to your commands in the terminal window. Thus, all functionality available in the terminal window is also available to your script (and mostly vice-versa).

    For example, we could write a for-loop that uses filename expansion (globbing) to print a list of all files in the current directory as follows:

    for file in *
    do
       echo $file
    done
  3. Write a script that uses this idea to print output similar to the following:
    Files in this directory that match *~ :
    bash-scripts.html~
    chimpanzee.sh~
    countdown.sh~
    countdown2.sh~
    hello.sh~
    TODO~

Part F: Some Useful Scripts

  1. This exercise is designed to give you some real-world examples of useful bash scripts. Therefore, you will write a couple of scripts actually used in teaching to automate clerical tasks. To begin, please copy this (ficitious) classlist.txt to your directory, and note that it contains a list of usernames.

    Write a script called addnames.sh that is to be called as

    ./addnames.sh classlist username

    where classlist is the name of the classlist file, and username is a particular student's username. The script should

    • check that the correct number of arguments was received and print an usage message if not,
    • check whether the classlist file exists and print an error message if not,
    • check whether the username is already in the file, and then either
      • print a message stating that the name already existed, or
      • add the name to the end of the list.

    Hint: Use a for-loop to process each line in the file. To create a list of lines in the file, remember that you can use any bash construct inside a script that you can use in the terminal window. How would you list the lines of the file in the terminal window? Similarly, how would you append a particular item to the end of an existing file from the terminal window?

    If you have not been doing so all along, you should now add some comments to your script and thoroughly test it!

  2. Write a script called submit-dirs.sh that is to be called as follows.

    ./submit-dirs.sh classlist

    The script should:

    • check whether the correct number of arguments was received and print a usage message if not,
    • check whether the classlist file exists and print an error message if not,
    • create a directory named submit within the current directory (but only if one does not already exist),
    • create a directory within the directory submit for each student in the class (but only if one does not already exist). These student directories should be named according to the students' usernames.
  3. Write a script called trash that takes a single argument, which should be the name of an existing file. The script should move the given file, if it exists, to a directory named trash that is located within your home directory. If the trash directory does not exist, the script should create it. If the given file does not exist, an appropriate error message should be printed.

    Hint: There are several "environment" variables that automatically exist within a bash script, including the following. You may want to explore what values these hold by echoing them to stdout.

    • $HOME
    • $USER
    • $PWD
    • $PATH

    The Bash shell manual page also contains descriptions of all its standard environment variables.

For Those with Extra Time

  1. Once your trash script is working well, modify it so that it accepts a list of files and moves all of them to the trash. The script should print an error message for each file that does not exist, and it should print a usage message if no file names are given.

    When testing your script, try invoking it with a command like the following:

    ./trash *.o
  2. If you would like to, you could begin a directory of bash scripts you would like to use regularly (such as trash). You can then add the name of that directory to your $PATH by following the instructions given below. Doing so will allow the scripts therein to be available to you regardless of which directory you are currently working in.

    To add a directory to your path, look for a file named .bash_profile in your home directory. It is a bash script that is run automatically when you log in. It should contain a line that defines the variable PATH. Note that the value assigned to this variable is a list of directories, delimited by colons. You can add your new script directory to your path by adding it to the end of this list. (That will cause bash to check your scripts directory after checking the others when search for programs to run.)

    After modifying your .bash_profile, you should also run ./bash_profile with the following command to update your running shell with the contents of your current path variable.

     source ~/.bash_profile