Tzafrir Cohen <[EMAIL PROTECTED]> writes:

> On Fri, Oct 24, 2003 at 10:47:22PM +0200, Oleg Goldshmidt wrote:
> > Shlomi Fish <[EMAIL PROTECTED]> writes:
> > 
> > > On Fri, 24 Oct 2003, Beni Cherniavsky wrote:
> > > 
> > > > Shlomi Fish wrote on 2003-10-12:
> > > >
> > > > > I want that if one of the (first) components of the pipeline exits with an
> > > > > error code, I'll know about it somehow. How?
> > > > >
> > > > info bash --index PIPESTATUS
> > > >
> > > 
> > > Cool thanks.
> > 
> > Depending on your needs you may also use the -e option to the shell
> > (should work for most Bourne shell and csh descendants), the option
> > will make the shell exit if any of the commands in the pipeline fails.
> > 
> > $ true | false | true
> > $ echo $?
> > 0
> > $ bash -e "true | false | true"
> > true | false | true: true | false | true: No such file or directory
> > $ echo $?
> > 1
> 
> This is because you tried running a script from a file called
> "true | false | true"
> 
> However:
> 
> $ set -e
> $ true | false | true
> $ echo $?
> 0
> 
> So setting that doesn't make an error from the middle of a pipe show.

Hmm, this seems to be true. What is weird about it, is that it is
supposed to do what I said. At least that is the way I used to read
the bash documentation and also the make documentation (which is where
I learned about -e from N years ago) - see below.

Check http://www.gnu.org/manual/make-3.77/html_node/make_43.html that
says

"Here is the pattern rule to generate a file of dependencies (i.e., a
makefile) called `name.d' from a C source file called `name.c':

%.d: %.c
        $(SHELL) -ec '$(CC) -M $(CPPFLAGS) $< \
                      | sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@; \
                      [ -s $@ ] || rm -f $@'

See section Defining and Redefining Pattern Rules, for information on
defining pattern rules. The `-e' flag to the shell makes it exit
immediately if the $(CC) command fails (exits with a nonzero
status). Normally the shell exits with the status of the last command
in the pipeline (sed in this case), so make would not notice a nonzero
status from the compiler."

Now, I created the following C file

#include "foo.h"

int main(void) { return 0; }

(cpp should fail because there is no foo.h), and the following
makefile:

%.d: %.c
        $(SHELL) -ec '$(CC) -M $(CPPFLAGS) $< \
                        | sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@'

(I don't want foo.d removed if it contains nothing, otherwise it is
identical to the example in the manual).

Guess what: make does not "notice a nonzero status from the compiler"
with or without -e.

So I got curious, and added

SHELL := csh

to the makefile, and - lo and behold! - it worked (csh is a symbolic
link to tcsh, and it works for both).

Now, "man tcsh" says

       -e  The  shell  exits  if  any  invoked command terminates
           abnormally or yields a non-zero exit status.

To compare, "man bash" says (for "set" builtin)

             -e      Exit  immediately  if a simple command (see
                      SHELL GRAMMAR above) exits with a  non-zero
                      status.   The  shell  does  not exit if the
                      command that fails is part of an  until  or
                      while  loop,  part of an if statement, part
                      of a && or || list,  or  if  the  command's
                      return  value  is  being inverted via !.  A
                      trap on ERR, if set, is executed before the
                      shell exits.
  
Further RTFMing ("man bash" is at your service) uncovered that bash
distinguishes between "simple commands", pipelines, and lists, and the
-e applies to simple commands only, as per above.

So it turns out that bash and tcsh behave differently. I apologize for
my misleading post - it only applies to t?csh, it seems, not to bash
(nor to zsh). I find it rather curious that the make documentation
does not mention the difference.

Now, I don't know what the rationale for bash behaviour is. It seems
to me that the way tcsh behaves is pretty useful.

-- 
Oleg Goldshmidt | [EMAIL PROTECTED]

=================================================================
To unsubscribe, send mail to [EMAIL PROTECTED] with
the word "unsubscribe" in the message body, e.g., run the command
echo unsubscribe | mail [EMAIL PROTECTED]

Reply via email to