|sections in this module||City
College of San Francisco - CS160B
Unix/Linux Shell Scripting
In introductory Unix, we experimented with standard input and standard output. Probably, one of the experiments you did was with the cat command:
cat < file1 > file2
Here, cat reads each line from standard input and writes the line to standard output. It continues until the end-of-file condition is reached on file1, then it stops.
In shell programming, we can read a line from standard input using the read command. The read command succeeds so long as a line can be read. If the input reaches end-of-file, however, the next read fails. This is exactly what happens in the cat command.
This 'failure' status can be tested in a while statement like this:
If you type this at the terminal, it is kind of silly, as the read command will read a line from the keyboard. Suppose we want to attach this to a file. One way to do this is:
This is perfectly legal. Here, however, file1 is re-opened each time the read command is encountered. We want to attach file1 to the loop so that it is opened when the loop starts, and each successive iteration reads another line from the file. We could do this
but if you recall, there are some issues with piping to loops and read commands, since the loop will now be executed in a child process. So long as you do not set any variables in the loop that you need after the loop has completed, this is fine. Alternately, we could redirect standard input to the loop:
This looks strange, but it is consistent with other unix commands: redirection normally appears at the end of the command, and the end of the while command is done.
I can't emphasize the importance of this, folks: this allows us to process anything we want, so long as we can create a file of the things to process, one-per-line.
Processing files with while read
We said previously that a for loop is useful for processing files, but that the list must be created with a wildcard, and may not be "too large". We can also process the files in a directory using a while loop.
Example: Ensure that each text file in the directory $dir has the extension .txt
We will iterate over the files in the directory. For each file that is a text file, we'll see if the filename ends in .txt (using grep to match the pattern), and, if it doesn't, rename it.
Note that we could have used a pipe here, as we do not set any variables in our loop that are needed when it exits. The loop would then look like:
There are two problems with our code:
How would you fix these problems? (see the Examples for this module for the solution.)
You may say: it was easier with a while loop. That is correct. But, suppose we wanted to do a job like this recursively to, say, all the files beneath our home directory. We could modify this loop easily for the task. You should not use a for loop for this, because the find command may output "too much" data for a for loop:
Processing command-line arguments
The most general loop for processing command-line arguments is the while loop. Most shell scripts do not have complex command-line arguments, and, if they do, they use the facility called getopts. getopts is covered pretty well in your book, so we won't cover it in the notes. We will, instead, go through a few examples of processing complex command-line arguments by hand. First, let's discuss the problems:
Our example will be for the fictitious command moo. moo has the following syntax
Here is how we will handle these options:
Here is the code for moo's argument handling. It is in this module's directory on hills.
|Preview question: In the next module we will discuss aliases, shell options, and substrings. Preview the information on aliases by looking at the bash man page and searching for the string Alias. (You can do this by typing /Alias followed by the ENTER key after you type man bash)|
|Prev|| This page was made entirely
with free software on linux:
Kompozer and Openoffice.org