Scripting Clinic: The Bash Continues

In this month's Scripting Clinic, we continue our look at Bash, the default command shell on most Linux distributions. We also offer more evidence of why scripting is good — regardless of what those Perl and C coders say.

 By Carla Schroder
Page 1 of 2
Print Article
Last month we took a tour of some Bash features, and learned that scripting is really just plumbing — a flexible, powerful way to combine Linux commands to accomplish complex tasks.

It's not uncommon, when discussing Bash scripting, for lordly Perl geeks to sniff disdainfully, and make helpful comments like "Your little 20-line Bash script is so amusing. I can do the same thing in Perl in a mere 300 lines." Or you get the hardbitten old C coders who think scripting of any kind is sissy — real geeks compile. Pay them no heed. Bash scripts are perfectly good tools.

Don't forget that "Linux In A Nutshell" is a great Bash reference, as well as the best all-around Linux reference. It's helpful to have all the Bash commands and keywords neatly separated from other Linux programs and commands. Much confusion in Linux comes from not understanding what belongs to what and this book keeps everything in its place.

Sha Bang
You've probably been told that it's better to use #!/bin/sh, which calls the Bourne shell, instead of #!/bin/bash, to make your scripts more portable. Well ya know, that's a personal decision. I've never touched a Unix box in my life, and chances are I never will. You lose some Bash functionality with #!/bin/sh. There's no point in preparing for some vaguely possible future; use what makes sense. If you're using Bash, write Bash scripts. If you prefer some other shell, go for it, and quit pestering Bash users.

Whichever one you elect to use, always be sure to make it the very first line of your scripts.

For/Do Loops
For/Do loops are great for performing batch operations on piles of files. The syntax is simple:

for variable-name in directory
do stuff

The Bash keywords are for, in, do, and done. Remember to not use these words for anything else, because they are reserved Bash words. (man bash has a list of reserved words.)

For example, suppose you want to convert a batch of audio files with the sox utility. sox does not have a built-in batch function, so Bash does the heavy lifting. This command converts all the .wav files in the current directory to .ogg format:

$ for i in *.wav ; do echo $i ; sox $i ${i%%.wav}.ogg ; echo ${i%%.wav}.ogg; done

Ok let's take this piece by piece.

$ for i in *.wav ;

i is the variable name that represents each filename, in turn, selected by the *.wav expression. *.wav means all files ending in .wav. It is traditional to use i for iterations. You can use almost anything- any letter of the alphabet, words, your name, whatever you want, as long as it is not a Bash reserved word. The semicolon ends the for statement. for will take each *.wav filename in turn, and pass it to

do echo $i;

All this does is print the output of $i, which is each filename in turn, to the screen. This lets you see what the command is doing. There can be only one for statement, and one do statement. But you can add any number of semi-colon delimited commands afterwards:

sox $i ${i%%.wav}.ogg ;

This is the meat of our little for loop. sox takes each .wav file, one at a time, and converts them to .ogg files. ${i%%.wav}.ogg means "remove the .wav extension." Without this, the files will be named soundfile.wav.ogg, instead of soundfile.ogg.

echo ${i%%.wav}.ogg;

This prints the converted filenames to the screen.


All finished! Because we can line up any number of commands after the the do statement, we need to tell for/do when their work is done.

Continued on Page 2: Cleaning Up

This article was originally published on Mar 16, 2004
Get the Latest Scoop with Networking Update Newsletter