Basic Shell Scripting

Basic Shell Scripting

In many of the other sections of the shell and utilities, we talked about a few programming constructs that you could use to create a quick script to perform some complex task. What if you wanted to repeat that task with different parameters each time? One simple solution is to is to re-type everything each time. Obviously not a happy thing.

The solution is to create a shell script we can use over and over again, which is the topic of this section. There are entire books on shell programming and to understand everything you probably need more material that any single book can provide. Rather than going through every possible shell constructs, we are going to cover more or less the basics. One of the things we will be using as a guide is how often a given construct appears in shell scripts that a standard Linux distribution provides by default and how important these constructs are to understanding the given script.

To create a shell script, we could use vi or some other text editor to create the file. However, we could take advantage of a characteristic of the cat command, which is normally used to output the contents of a file to the screen. You can also redirect the cat to another file.

If we wanted to combine the contents of a file, we could do something like this:

cat file1 file2 file3 >newfile

This would combine file1, file2, and file3 into newfile.

What happens if we leave the names of the source files out? In this instance, our command would look like this:

cat > newfile

Now, cat will take its input from the default input file, stdin. We can now type in lines, one at a time. When we are done, we tell cat to close the file by sending it an end-of-file character, Ctrl-D. So, to create the new command, we would issue the cat command as above and type in our command as the following:

for j in boat ship yacht do find ./letters/taxes -type f | xargs grep -i $j done

Note that here the secondary prompt, >, does not appear because it is cat that is reading our input and not the shell. We now have a file containing the five lines that we typed in that we can use as a shell script. So, being able to create new scripts with the cat.

Granted to be able to edit the file using vi is fairly straight forward. However, I have worked on a number of systems were vi was disabled for everyone but the administrator or I accessed the machine through a connection that made using vi difficult.

In order to fully understand this we need to look at the for-in construct and the do-done pair. You will find the do-done pair in a number of contexts. In short, it defines the block of commands to be executed by the preceeding construct. In this case the for-in construct. You will also find a do-done pair when creating loops using while, as well as other places.

In the example above, the for-in construct looked like this:

for j in boat ship yacht

In essence this loops through the statements in the do-done block once for each of the values listed: boat ship yacht. Each time through the loop, the respective value is assigned to the variable j. So, the first time j=boot, the second time j=ship and the third time j=yacht.

We did not need to use a single letter here. Instead, we could have used any valid variable. For example, we could have called it SEARCHWORD, if we wanted.

In our example, the lines within the do-done block are executed three times. Here we only have a single line, but could have essentially any number of lines within a do-done block.

This example also uses the xargs command. The example here is perhaps the simplest form you will find xargs. As you can see, it is the end of the pipe from the find which is simply finding every single file in the directory ./letters/taxes. Thus, xargs is getting a list of files feed into it’s standard input. It then creates a command using grep which searches through each of the files passed through the pipe.

Keep in mind that we have the variable $j which changes during each pass through the loop. So, the first time through the look the xargs command would look like this:

xargs grep -i boot

Therefore, this would search through each of the file looking for “boot”. Note that the -i says to ingore the case.

However, right now, all that we have is a file named newfile that contains five lines. We need to tell the system that it is a shell script that can be executed. Remember in our discussion on operating system basics that I said that a file’s permissions need to be set to be able to execute the file. To change the permissions, we need a new command: chmod. (Read as “change mode” because we are changing the mode of the file.)

The chmod command is used to not only change access to a file, but also to tell the system that it should try to execute the command. I said “try” because the system would read that file, line-by-line, and would try to execute each line. If we typed in some garbage in a shell script, the system would try to execute each line and would probably report “not found” for every line.

To make a file execute properly, we need to give it execute permissions. To give everyone execution permissions, you use the chmod command like this:

chmod +x newfile

Now the file newfile has execute permissions, so, in a sense, it is executable. However, remember that I said that with a shell scripts, the system would read each line and try to parse it. In order for a shell script to function correctly, it also needs to be readable by the person executing it. In order to read a file, you need to have read permission on that file. More than likely, you already have read permissions on the file since you created it. However, since we gave everyone execution permissions, let’s give them all read permissions as well, like this:

chmod +r newfile

You now have a new command called newfile. This can be executed just like any the system provides for you. If that file resides in a directory somewhere in your path, all you need to do is type it in. Otherwise, (as we talked about before) you need to enter in the path as well. Keep in mind that the system does not need to be able to read binary programs. All it needs to be able to do is execute them. Now you have your first shell script and your first self-written Linux command.