Tuesday, February 12, 2008

A Great Bash Scripting Nugget...

Hello Again,

In the past few days while working on a automated provisioning script for Sun's implementation of Xen for Solaris called xVM. During that journey Bernd Eggink rescued me by introducing me to the "here strings" feature of bash. So for everyone's benefit, I would like to share my pilgrimage with you for your benefit.

Here is a sample bash script that populates an array (FileList) with a variable (File) that is populated from the output of ls -1. This is the way that I have traditionally populated an array from the output of a command.

declare -a FileList=('')
declare -i d=0

ls -1| while read File
do
FileList[${d}]=${File}
d=$((10#${d}+1))
done

This used to work on earlier versions of bash and still works for Solaris ksh. However, it does not work on bash version 3.2.25(1). Bernd explains why this no longer works in bash below:

This is normal bash behaviour, see FAQ E4. As bash executes _all_ parts of a pipe in subshells (in contrast to ksh, where the last component is executed in the current shell), the variable 'FileList' being assigned here is local to the subshell. After the loop the variable 'FileList' declared in line 1 (which happens to have the same name, but that doesn't matter) is unchanged.
Here is the example that Bernd suggested as an alternative which worked great.

while read File
do
FileList[d]=$File
(( d=d+1 ))
done <<<"$(ls -1)"

I went back to my favorite bash reference, The Advanced Bash Scripting Guide by Mendel Cooper to see if this sort of example was already in there and I just overlooked it. To my surprise I found the following even more succinct example in section 18.1 (Here Strings).
read -r -a FileList <<< $(ls -1)

So if you want a really succinct and simple method of populating an array vi command line put, I suggest this last example.

Have a great scripting day!!!

Thanks again Bernd! And thanks Mendel for your great guide!

Brad

0 comments: