Bash – Iterating over glob patterns, not the files in them

bashforshell-scriptwildcards

I would like to perform the same aggregation operations on each of several bunches of files where each bunch is matched by one glob pattern. What I would not like to do is pipe each file name into the aggregation function separately.

My first attempt failed because the file names got globbed in the outer loop, flattening the whole collection into a flat list and not treating them as separate batches:

for fileglob in /path/to/bunch*1 /path/to/bunch*2 ... ; do
  stat "$fileglob" | awk [aggregation]
done

So I hid the * from the loop by escaping it, then unescaped it for the function:

for fileglob in /path/to/bunch*1 /path/to/bunch*2 ... ; do
  realglob=`echo "$fileglob" | sed 's/\\//g'`
  stat "$realglob" | awk [aggregation]
done

There has to be a better way. What is it?

GNU bash, version 3.2.51

Best Answer

This requires a careful use of quotes:

for fileglob in '/path/to/bunch*1' '/path/to/bunch*2' ... ; do
    stat $fileglob | awk [aggregation]
done

But that may fail on filenames with spaces (or newlines). Better to use this:

fileglobs=("/path/to/bunch*1" "/path/to/bunch*2")

for aglob in "${fileglobs[@]}" ; do
    set -- $aglob
    stat "$@" | awk [aggregation]
done

The glob gets correctly expanded and placed in the positional parameters with:

set -- $aglob

Then, each parameter is placed as an argument to stat in:

stat "$@"

And the output of stat goes (as one output) to awk.

Related Question