October 21, 2010

Essentials of Bash Scripting: Using Loops

 

An essential rule of system administration: If you need to do something often, try to write a script to do it for you. If you need to do something several times within a script, you'll need to be able to use loop statements to repeat something until done. With GNU Bash, you'll do this with for, while, and until statements.

If you've done any programming, you're probably familiar with these statements already. If you're like me, and were introduced to bash scripting without benefit of a programming background, they might not be quite so obvious. Let's start by explaining the differences between the statements, and then move on to examples.

The for loop is used to iterate through an action until done. Let's say you have a directory full of images that you want to convert from one format to another. You could use a for loop and ImageMagick's convert (or another program) to convert JPEG images into PNG format, for instance. Or create a script to take a directory full of MP3s or WAV files and convert to Ogg Vorbis.

The while loop is used to perform an action while a condition is true, and until does the opposite — it performs an action until a condition is true. So you might run a counter, for example, up to 10 and perform an action until the counter hits 10. We'll look at this more closely in the examples.

Using for Loops

Let's start with the for loop. The syntax is:

for i in $( command ); do command $i; done

That's on the command line. If you're doing a script, you'd format it as:

#!/bin/bash
for i in $( command ); do
command $i
done

So, if I wanted to make a backup copy of all the HTML files in a directory, I'd use:

for i in $( ls *html ); do cp $i $i.bak; done

So set up a variable (i), and then set up the command that will give the loop something to iterate over (ls *html). Next, do the action cp to the files that ls *html returns, one at a time.

You might be wondering, does the variable have to be i? Nope. It could any valid variable name. If you want to write a more readable script, you can give it a name like input or html.

Here's a quick tip while you get started: Use echo to replace the command you wish to run as a test-run. For instance, if you're iterating through a directory and performing an operation on files, use echo to give the name of the files the first time through. That way you'll see that the script is performing as intended, and if not echo is non-destructive so there's no harm, no foul if it doesn't do what you meant to do. Then you can do the real action without fear.

Using while and until

Next up, we'll take while and until for a test drive. We're also going to use some Bash conditionals. These are used to evaluate an expression like "is a variable larger or smaller than X?" or "does a this file exist, and is it a directory?" You might want to use a conditional to ensure that a file exists and is readable, or to ensure that a file exists and has its set group ID (sgid) bit set.

Let's do something simple, and create some empty files. Not very useful, but a good example. Here we go:

i=0
while [ $i -lt 22 ]
do
touch $i
i=$[$i+1]
done

This will create file name 0 through 21. Remember, it's while the variable is less than (-lt) 22, so it starts at zero and stops at 21.

Now let's get rid of those file by changing the script around with a until statement:

i=0 

until [ $i -eq 22 ]
do 
   rm $i
   i=$[$i+1]
done

All we've had to do here is flip while to until, and change the conditional to equal (-eq) so that the until loop runs until the variable is equal to 22. Instead of touching a file, we're removing the files. Easy, right?

In the next installment, we'll look at conditionals in more detail, and using them with the for, while, and until loops to do some standard system administration tasks. Until then, try these out on your machine and see what you can do to automate your work on Linux!

Click Here!