Thursday, February 21, 2008

How to Write Shell Scripts

A friend posted a note on the BLUG mailing list about a shell script he was having trouble with:

#!/bin/bash

declare -xi total=0
declare -xi count

cat /tmp/orders | while read file;do
wc -l /dgorder/$file;
done | while read count file;do
total=$((total + count))
done

echo "Number of Orders: $(wc -l /tmp/orders | tr -s ' '|cut -d' ' -f2)"
echo "Total Documents: $total"

/tmp/orders is a file that has a filename, one per line

Each /dgorder/$file has a number of records in it and I'm trying to
count the total number of records in all the files.
It wasn't working. Here's my solution, with commentary

You're just trying to be too clever. Here's an easier way, done by, "recall the line and add something." Programming by accretion. :-)

$ cat /tmp/foo
fstab
passwd
group
$ for i in $(< /tmp/foo); do echo /etc/$i; done # Want to ensure they exist? s/echo/ls/
/etc/fstab
/etc/passwd
/etc/group
$ wc -l $(for i in $(< /tmp/foo); do echo /etc/$i; done)
39 /etc/fstab
81 /etc/group
54 /etc/passwd
174 total
$ wc -l $(for i in $(< /tmp/foo); do echo /etc/$i; done) | perl -lane 'print if s/ total//'
174
$ total=$(wc -l $(for i in $(< /tmp/foo); do echo /etc/$i; done) | perl -lane 'print if s/ total//')
$ echo $total
174
It shows how I start out writing all of my shell scripts: on the command line.

At this point, I can use the bash built-in, fc, to put the code into a file, and save it as the core of a working script.

As an added bonus, he told me he debugged his, after he'd sent the note, but it was a factor of ten slower than mine.

Still, in most of my code, what's important is speed of development. I could probably, make it even faster, but only with more work. This really did only take the half a dozen steps shown above to develop.

No comments: