Shell scripting (extra material)

Scripting is useful to perform complex interaction with programs and data. We revise basic commands to write simple bash scripts.

Variables

Values can be assigned to variables using = symbol and can be referred to by prepending a $:

$ var1=goofy
$ var2=pluto
$ echo $var2 is $var1\'s dog
pluto is goofy's dog

Notice that = symbol needs to be near variable name and value, adding spaces would give an error as var1 would be considered a command to execute:

$ var1 = goofy
var1: command not found

Inside double quotes variables are still replaced with their value. Notice that with double quotes it is not necessary to escape the single quote:

$ var1=goofy
$ var2=pluto
$ echo "$var2 is $var1's dog"
pluto is goofy's dog

Single quotes, instead, prevent variable replacement, as shown below. Notice that we need to close the quote, escape the ‘ character we want to print and reopen the single quote:

$ var1=goofy
$ var2=pluto
$ echo '$var2 is $var1'\''s dog'
$var2 is $var1's dog

Finally, it is possible to concatenate commands using ; and to break into different lines by ending each line with \. For example:

$ var1=goofy; var2=pluto; echo "$var2 is $var1's dog"
pluto is goofy's dog
$ var1=goofy;\
> var2=pluto;\
> echo "$var2 is $var1's dog"
pluto is goofy's dog

Executable script files

Writing long sequences of commands on the command-line might become complicate. It is possible to write scripts in files and execute them, as we would do with programs. It is important to remember, however, that shell scripts are interpreted by the shell as if they were entered from the command line. There is no compiler or static analysis of the code.
When we write a shell script we need to start with a directive telling the system what interpreter will be used. For example, using bash, we will write:

#!/bin/bash
var1=goofy
var2=pluto
echo "$var2 is $var1's dog"

We can save this in a file named script1.sh, make it executable with chmod u+x script1.sh and execute it:

$ ./script1.sh
pluto is goofy's dog

Exercise 1

Write a script that generates and execute another script that, in turns, prints Hello World.

Parameters

Parameters passed on the command line can be accessed by scripts through special variables:

  • $0, $1, … , $n refer to parameters 0, 1, … , n;
  • $# contains the number of parameters;
  • $@ contains the list of all parameters, separated by a blank space.

For example:

#!/bin/bash
echo "Number of parameters: $#"
echo "List of parameters:   $@"

gives the following output:

$ ./script-parameters.sh 1 2 3 test hello world
Number of parameters: 6
List of parameters:   1 2 3 test hello world

Iterating over list elements (for loop)

In order to process parameters (or in general elements of a list) one by one, we can use a for loop as follows:

#!/bin/bash
for par in $@
do
        echo $par
done

which behaves as follows:

$ ./script-for-loop.sh 1 2 3 test hello world
1
2
3
test
hello
world

Conditionals

We give a simple example of if-then-else constructs:

#!/bin/bash
if [ "$#" -ne 2 ]
then
        echo "[ERROR] Two parameters expected"
        exit
fi
if [ "$1" -eq "$2" ]
then
        echo "$1 = $2"
elif [ "$1" -gt "$2" ]
then
        echo "$1 > $2"
elif [ "$1" -lt "$2" ]
then
        echo "$1 < $2"
else
        echo "[ERROR] Something went wrong, you should insert numbers"
fi

Here is what we get when we execute the script:

$ ./script-if.sh
[ERROR] Two parameters expected
$ ./script-if.sh 1 2 3
[ERROR] Two parameters expected
$ ./script-if.sh 1 2
1 < 2
$ ./script-if.sh 2 2
2 = 2
$ ./script-if.sh 3 2
3 > 2
$ ./script-if.sh 3 hello
./script-if.sh: line 7: [: hello: integer expression expected
./script-if.sh: line 10: [: hello: integer expression expected
./script-if.sh: line 13: [: hello: integer expression expected
[ERROR] Something went wrong, you should insert numbers

Notice that numeric comparisons cannot be performed using < and > since the shell treats them as redirection operators. To see the full list of expressions supported type man [ or, equivalently, man test.

Command substitution

It is often very useful to execute a command and assign its output to a variable. This can be done using syntax $( command ). An example follows:

$ ls
file1.txt  mysite.html  script.sh
$ myls="$( ls )"
$ echo "$myls"
file1.txt mysite.html script.sh

Exercise 2

Write a script that renames any .html file into uppercase .HTM ones. For example website.html should become WEBSITE.HTM. Renaming can be done via mv command while name conversion has been treated in Exercise 2 of previous class.

References

  1. https://supportweb.cs.bham.ac.uk/docs/tutorials/docsystem/build/tutorials/unixscripting/unixscripting.html