Avoiding errors due to unexpanded asterisk

In bash I often use for-loops such as the following

for file in *.type; do 
  sommecommand "$file"; 
done;

to perform an operation for all files matching *.type. If no file with this ending is found in the working directories the asterisk is not expanded and usually I will get an error message saying that somecommand didn’t find the file. I can immediately think of several ways to avoid this error. But adding a conditional does not seem to be very elegant. Is there a short and clean way to achieve this?

Asked By: highsciguy

||

Yes, run the following command :

shopt -s nullglob

it will nullify the match and no error will be triggered.

  • if you want this behaviour by default, add the command in your ~/.bashrc
  • if you want to detect a null glob in POSIX shell, try

    for i in *.txt; do
      [ "$i" = '*.txt' ] && [ ! -e '*.txt' ] && continue
    done
    

See http://mywiki.wooledge.org/NullGlob

Answered By: Gilles Quenot

In bash you can use shopt -s nullglob to expand to an empty array if there are no matches.

In POSIX shells without nullglob, you can avoid this problem by checking that the filename being passed actually exists by having [ -e "$file" ] || [ -L "$file" ] || continue as the first part of your for loop.

Answered By: Chris Down

The usual technique for shells that don’t have a nullglob option is

set -- [*].type *.type
case $1$2 in
  '[*].type*.type') shift 2;;
  *) shift
esac
for file do
  cmd  -- "$file"
done

The extra [*].type is to cover the case where there’s one file called *.type in the current directory.

Now, if you want to include dot files, that becomes more complicated.

I beleive that technique was coined by Laura Fairhead on usenet a few years ago.

Answered By: Stéphane Chazelas

find . -name '*.type' -maxdepth 0 -exec somecommand "{}" ";"

This removes the for loop and the shell’s globbing from the equation entirely. find will execute the -exec command once per match, and if there are no matches, it will never be executed. The -maxdepth 0 instructs find to not recurse into subdirectories of the named path-argument (., in this case).

The downside is that it involves another application, albeit one that is present on virtually every Linux system out there (and probably most Unixes as well).

Answered By: user
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.