Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how do I guard against "foreach: No match"?

Tags:

shell

csh

tcsh

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?

like image 280
dromodel Avatar asked Aug 20 '13 17:08

dromodel


2 Answers

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.

like image 192
rob mayoff Avatar answered Nov 10 '22 00:11

rob mayoff


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.

like image 24
Keith Thompson Avatar answered Nov 09 '22 23:11

Keith Thompson