CSE 374, Lecture 4: Shell Scripts

We'll start with the makethumbnail program that we were working on last lecture.

Variables

In the intro to CS classes we learned that copy and pasting code is bad. In this case we have the two djpeg lines that are very similar. Can we do better? Yes, if we can use VARIABLES, which bash has.

    xsize=100
    ysize=150

    if [ $# == 4 ]
    then
      xsize=$3
      ysize=$4
    elif [ $# != 2 ]
    then
      echo "$0: need 2 arguments: source-jpeg destination-file x-size y-size"
      exit 1
    fi

    djpeg < $1 | pamscale -xysize $xsize $ysize | cjpeg > $2

We refer to variables by name with $.

How are these variables different than the variables we are used to in Java?

Special variables

There are a number of shell variables that are used in bash itself and that have special meanings.

Export

We've also seen the "export" command show up in the .bashrc file last week. But what does export mean?

If we have a shell script called "echox" that looks like the following:

    #!/bin/bash
    echo $x

And then we run it in the terminal like so:

    $ x="hello world"
    $ ./echox

Will it print "hello world"? The answer is no! The variable x that you set before running the script is NOT visible to the script. But you can make it visible using export:

    $ export x="hello world"
    $ ./echox
    hello world

This is what we use in .bashrc - so that those variables that we set are visible to any other scripts that you run.

Loops and math

Let's write another script to output the fibonacci sequence. The fibonacci sequence is the sequence of numbers where the next one is the sum of the previous two.

    1 1 2 3 5 8 13 21 ...

Let's just print the numbers that are less than 500. We'll need a loop to do this.

    #!/bin/bash

    first=1
    second=1
    echo $first
    echo $second

    while [ $second -lt 500 ]
    do
      sum=$((first+second))
      echo $sum
      first=$second
      second=$sum
    done

Here we also see how to do arithmetic expressions - we need to do $((expr)) - as well as numeric comparisons (-lt operator). In the condition statement of an if or while, you can also use standard logic operators like &&, ||, and !. Since all variables are actually strings, when you have the double parentheses the shell will try to use the strings as numbers. If a variable actually does NOT store a number, the shell will silently substitute 0.

What if we were to try to do addition as $first+$second? It wouldn't work! That's because all variables are actually stored as strings, and + will do concatenation instead. We need the double parentheses in order to signal to bash that we actually want an arithmetic operation.

Check out "file tests" as well - another option for the inside of an if/while statement. Modify our makethumbnail script to check whether the input image file actually exists, and print out an error message if it doesn't.

Shell script gotchas

shift

Our final script of the day is called "countdown". This program will print out the arguments given to it in triangular design:

        $ ./countdown a b c d e
        a b c d e
        b c d e
        c d e
        d e
        e

I also introduced a command called "shift". "shift" takes the arguments given to script and discards the first one, "shifting" the arguments over by one position, as so:

    # At the beginning, $1 is a, $2 is b, $3 is c, ...
    shift
    # Now, $1 is b, $2 is c, $3 is d, ...

How can we solve this problem with this command?

Approach one: use a for loop!

    #!/bin/bash
    # Save the number of arguments in a variable, because when we switch, the number changes
    num=$#
    for i in $(seq 1 $num)
    do
      echo "$@"
      shift
    done

There are a couple of new things going on here:

We could also do the same thing with a while loop:

    while [ $# -gt 0 ]
    do
      echo "$@"
      shift
    done