Flow Control - Part 3

Now that you have learned about positional
parameters, it is time to cover the remaining flow
control statement, for. Like
while and until, for is
used to construct loops. for
works like this:

for variable in words; do
commands
done

In essence, for assigns a
word from the list of words to the specified
variable, executes the commands, and repeats this
over and over until all the words have been used
up. Here is an example:

#!/bin/bash
for i in word1 word2 word3; doecho $i
done

In this example, the variable i is
assigned the string "word1", then the
statement echo $i is executed, then the
variable i is assigned the string
"word2", and the statement echo $i
is executed, and so on, until all the words in the
list of words have been assigned.

The interesting thing about for is the many ways you can construct
the list of words. All kinds of expansions can
be used. In the next example, we will construct the
list of words using command substitution:

Here we take the file .bash_profile and
count the number of words in the file and the
number of characters in each word.

So what's this got to do with positional
parameters? Well, one of the features of for is that it can use the positional
parameters as the list of words:

#!/bin/bash
for i in "$@"; doecho $i
done

The shell variable "$@" contains the list
of command line arguments. This technique is often used to process a list of files on
the command line. Here is a another example:

#!/bin/bash
for filename in "$@"; do
result=
if[ -f "$filename" ];then
result="$filename is a regular file"
elseif[ -d "$filename" ];then
result="$filename is a directory"
fifiif[ -w "$filename" ];then
result="$result and it is writable"
else
result="$result and it is not writable"
fiecho "$result"
done

Try this script. Give it a list of files or a
wildcard like "*" to see it work.

Here is another example script. This one
compares the files in two directories and lists
which files in the first directory are missing from
the second.

This improved version introduces a new command
printf, which is
used to produce formatted output according to the
contents of a format string. printf comes from the C programming
language and has been implemented in many other
programming languages including C++, Perl, awk,
java, PHP, and of course, bash. You can read more
about printf format strings
at:

We also introduce the find command. find is used to search for files
or directories that meet specific criteria. In the
home_space function, we use find to list the directories and
regular files in each home directory. Using the wc command, we count the number
of files and directories found.

The really interesting thing about
home_space is how we deal with the problem
of superuser access. You will notice that we test
for the superuser with id and,
according to the outcome of the test, we assign
different strings to the variable
dir_list, which becomes the list of words
for the for loop that
follows. This way, if an ordinary user runs the
script, only his/her home directory will be
listed.

Another function that can use a for loop is our unfinished
system_info function. We can build it like
this:

system_info()
{
# Find any release files in /etc
if ls /etc/*release 1>/dev/null 2>&1; thenecho "<h2>System release info</h2>"
echo "<pre>"
for i in /etc/*release; do
# Since we can't be sure of the
# length of the file, only
# display the first line.
head -n 1 $i
done
uname -orp
echo "</pre>"
fi
} # end of system_info

In this function, we first determine if there
are any release files to process. The release files
contain the name of the vendor and the version of
the distribution. They are located in the
/etc directory. To detect them, we perform
an ls command and throw away
all of its output. We are only interested in the
exit status. It will be true if any files are
found.

Next, we output the HTML for this section of the
page, since we now know that there are release files
to process. To process the files, we start a for loop to act on each one.
Inside the loop, we use the head command
to return the first line of each file.

Finally, we use the uname command with
the "o", "r", and "p" options to obtain some
additional information from the system.