BASH Shell Scripting

30 November -0001
April 21, 2003

Shell scripts are small programs comprised of BASH shell commands. All a shell script really is is a series of BASH commands saved as a text file and made executable. For example: you can type the simple command 'whoami'

$ whoami
jkeane

This command simply echoes the user you are currently logged in as. You could put this command into a text file, and use it as a shell script quite simply. Echo the command into a text file by using pico. Keep in mind that the conventional extension for shell scripts is '.sh'. To echo the command into a text file you can use the '<' or redirect operator. '>' moves whatever output results from a command into a file.

For instance:

$ whoami > yell.txt

Will create a new file called 'yell.txt' in your current directory containing the output of the whoami command (in this case 'jkeane'). You can check the contents using less:

$ less yell.txt
jkeane

If you want to put the text 'whoami' into the file you can use the 'echo' command. Echo will simply mirror back whatever output you type after echo. For instance:

$ echo 'hello world'
hello world

So if we want to create a text file with the command 'whoami' in it we can use:

$ echo 'whoami' > yell.sh

And we will create a file called 'yell.sh' containing one line with the word 'whoami' in it. If you use the '>' command to move more information into yell.sh the original contents will be overwritten. For instance:

$ echo 'whoami' > yell.sh
$ echo 'ls' > yell.sh
$ less yell.sh
ls

If you want to append information to your file without overwriting the original use the double greater than operator ('>>') and the information will be appended without deleting the contents. For instance, given the contents of our 'yell.sh' as described above, we can:

$ echo 'whoami' >> yell.sh
$ less yell.sh
ls
whoami

And now we have a series of commands in our file. Now, to create a shell script all you have to do is make your file executable. You can use the 'chmod' to do this:

$ echo 'whoami' > yell.sh
$ chmod +x yell.sh
$ ls *.sh -la
-rwxrwxr-x    1 jkeane   jkeane          7 Apr 21 09:16 yell.sh*

The only problem with this modification is that everyone can now execute your shell script. You're probably safer using:

$ chmod +700 yell.sh

This makes your file readable(+4), writable(+2) and executable(+1) by the owner (you) and nobody else. Once your file is executable you can run it. You have to use the './' modifier to execute the file unless the current directory is in your PATH or directories that the shell will search to find executables. You can find your PATH variable by taking a look at your .bash_profile (which is found in your home directory) or by issuing:

$ echo $PATH

If you want to add your home directory (or any directory for that matter) to your $PATH variable you can edit your .bash_profile and add a new line containing 'PATH $PATH:/home/jkeane' (substituting your own home directory for /home/jkeane) below the line 'PATH=$PATH:$HOME/bin'. Assuming you haven't added the directory containing your 'yell.sh' file to your $PATH variable you can run it like so:

$ ./yell.sh
jkeane

The './' tells BASH to execute the program in the current directory (ignoring your PATH directories) and you'll see the executing 'yell.sh' simply executes the commands contained in the text file line by line. If you want to issue multiple commands on the same line you can separate them with a semi-colon. For instance:

$ pwd ; whoami
/home/jkeane
jkeane

If you want to use variables in a shell program you can use them by simply craeting a variable name (containing letters, numbers and underscores starting with a letter or underscore) and setting its value. For instance:

$ MYVAR=1

sets the variable 'MYVAR' and assigns it a value of 1. Note however that we can't do arithmatic directly in the BASH shell. So if you issue:

$ myvar=1
$ myvar2=2
$ echo $myvar+$myvar2
1+2

If you want to do math you have to use the 'let' command. For instance:

$ let "myvar = myvar + 2"
$ echo $myvar
3

If you do any extensive shell programming you're also going to want to be able to use the output from one command in another. To do this you use the pipe (|) symbol. A pipe moves output from one command to a different program or command. For instance, if you wanted to list the contents of a directory, but view them using the less program (so you could scroll up and down using the arrow keys) rather than having them spill onto the screen, you could use a pipe like so:

$ ls -la | less

The pipe moves the output from 'ls -la' to the less command. Similarly you can use pipes and bc to do math in a shell:

$ echo "$myvar + 1" | bc
2

Now lets actually string together some commands with some flow control to make a real shell script! The first thing we're going to do is open up 'yell.sh' in a text editor. Next we'll change the contents to make a small shell script that searches the current directory for the file 'foo.sh'. Copy the following into your yell.sh file using vi, emacs, or pico:

if (ls -la | grep "foo.sh"); then
        echo "found foo.sh"
else
        echo "can't find foo.sh"
fi

Then run yell.sh:

$ yell.sh
can't find foo.sh

And you can see the output. What the shell script is doing is using an if else statement. What we're doing is checking to see if the command 'ls -la | grep "foo.sh"' returns any output. If it does then the shell script will echo 'found foo.sh', otherwise the 'can't find foo.sh' line will echo back. You'll notice that the if statement is followed by a semi-colon and a 'then' statement (similar to Visual Basic). The else is fairly obvious, and then the if statement must be closed with 'fi'. If you have multiple else statements you can use 'elseif'.

You can also perform do while loops in shell scripts. A simple do while loop can be used to print out numbers 0 through 10. Simply alter your 'yell.sh' script to include:

x=0
echo $x
while [ $x -lt 11 ]
do
        let "x += 1"
        echo $x
done

The syntax is rather picky so be sure to include all the necessary spaces and breaks. The only thing that bears explaining in the above example is the '-lt' part. This is the 'less than' operator, '-gt' is greater than, '-le' is less than or equal and '-ge' is greater than or equal.

Using all of this you should be able to script up a pretty simple shell script. For instance, if you know there are 10 sequentially numbered photos (say 'picture1.jpg' through 'picture10.jgp' on a website and you want to download them all you could use the following shell script to grab all the pictures:

x=1
theURL='http://www.somesite.com/images/picture'
while [ $x -le 10 ]
do
        theGo=$theURL$x".jpg"
        wget $theGo
        let "x += 1"
done

And there you have it :) At this point you should understand the power of shell scripts for all sorts of tasks. For more information you might want to check out: The Linux Documentation Project.

Enjoy.