[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Why has "find ... -exec rm -i '{}' ';'" stopped working?



On Tue, Jul 05, 2005 at 12:41:48PM +0100, Adam Funk wrote:
> michael wrote:
> > Well on 'sarge', under bash, the
> >   find . -name 'whatever' -exec rm -i {} ";"
> > works as expected for me, but the above example exhibits the same
> > performance as you note (I'm no 'xargs' expert and can's see what the
> > '-0r' option is meant to do)
> > 
> > If I were you I'd check that the first form works from the command line
> > and then take it from there. 
> 
> Sorry if I wasn't clear.  When I said this:
> 
> --> Typing "find -name '*~' -exec rm -i '{}' ';'" directly
> --> prints a list of rm-questions, doesn't get an answer, and so
> --> does nothing.
> 
> I meant that typing "find..." directly at a shell prompt doesn't work.  I
> also tried it as "find -name '*~' -exec rm -i {} ';'" and got the same
> problem.  (For some reason I used to have to quote {}.)
> 
> > Are you running bash under sarge? 
> 
> I'm running "testing", and dpkg says I'm using bash 3.0-15 and findutils
> 4.2.22-1.

It seems to be a bug (or feature?) of find.
(I can even reproduce the behaviour when moving the debian-testing find
binary to a somewhat older SuSE box -- where the command in question
does read from stdin otherwise)...

Actually, it appears to be caused by a change in the upstream sources
of find:  comparing the respective strace outputs, one can observe
that stdin in fact is being closed in the new (4.2.22) version before
launching the child process rm -- while it is not in the old.

Digging a little deeper, one finds in the sources a function which is
most likely responsible (--> close(0), followed by reopening it to
/dev/null):

  static void
  prep_child_for_exec (void)
  {
    const char inputfile[] = "/dev/null";
    /* fprintf(stderr, "attaching stdin to /dev/null\n"); */

    close(0);
    if (open(inputfile, O_RDONLY) < 0)
      {
        /* This is not entirely fatal, since
         * executing the child with a closed
         * stdin is almost as good as executing it
         * with its stdin attached to /dev/null.
         */
        error (0, errno, "%s", inputfile);
      }
  }

(It's called from within launch(), which is handling the option -exec)

This function is simply not present in the old sources (4.1.20).

Well, I guess it's worth filing a bug report, to let the original
authors figure out what it was that made them add this code -- and
whether there is a way to work around the issue.  Apparently, they
didn't think anyone would ever want to do something like you do... ;)

Cheers,
Almut


P.S.  The reason that "find ... -print0 | xargs -0r rm -i" exhibits the
same behaviour is a different one:  Here, find's stdin filehandle would
somehow have to be passed through to rm (via xargs, which in turn has
its stdin attached to find's stdout), in order for rm to be able to
read from the current interactive tty.  I'd think that such indirect,
bidirectional pipes simply seemed too cumbersome to implement...



Reply to: