6

I've got a shell script that looks like this:

foreach dir (i686.* amd64.*)
  # commands
end

The problem with this script is that if there are no directories matching those names then I get the following error:

"foreach: No match."

What's an elegant way to guard against this error?

devnull
  • 118,548
  • 33
  • 236
  • 227
dromodel
  • 9,581
  • 12
  • 47
  • 65

2 Answers2

6

Here are two ways to handle this.

  1. Set the shell's nonomatch variable. This tells tcsh to leave a pattern unchanged if it doesn't match any files. Thus:

    % set nonomatch=1
    % echo i686.* amd64.*
    i686.* amd64.*
    

    You will then need to make your commands handle the case of a non-matched pattern.

  2. Pass an extra pattern that always matches. Example:

    % echo i686.* amd64.* /dev/nul[l]
    /dev/null
    

    You will then need to make your commands ignore the file matched by the always-matched pattern. This is probably easier than #1.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
3

You can use grep or egrep rather than a file matching pattern:

foreach dir ( `ls | egrep '^(i686\|amd64)\.'` )
    # commands
end

If no files match, the ls | egrep ... command simply won't produce any output, and the body of your loop won't execute.

Given the name dir, you might want to add a test that any matching file name is actually a directory.

An uglier alternative is to temporarily create a matching file:

tmp=i686.$$
mkdir $tmp
foreach dir (i686.* amd64.*)
    if ($dir != $tmp) then
        # commands
    endif
end
rm $tmp

I don't necessarily recommend this.

You might want to use a :q suffix or add double quotes if you need to worry about directory names containing funny characters.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631