coreutils
[Top][All Lists]
Advanced

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

Re: find !(*.iso) -exec rm '{}' + fails when encounters filename beginni


From: Bob Proulx
Subject: Re: find !(*.iso) -exec rm '{}' + fails when encounters filename beginning with -
Date: Mon, 21 Nov 2011 13:15:11 -0700
User-agent: Mutt/1.5.21 (2010-09-15)

Graham Lawrence wrote:
> find !(*.iso) -exec rm '{}' +    # remove all but *.iso, needs shopt -s 
> extglob

Did you mean to send this to the coreutils discussion list?  Or did
you mean to send this to the bug-findutils list?  Your problem is
related to a combination of the shell and find and not any of the
coreutils programs.  Oh well.

Using !(*.iso) is a bash shell expansion.  It seems very inconsistent
to me to use find for part and use shell for a different part.
Personally for that I would use find for both parts.  But if you want
to use the shell you need to be aware that the shell is expanding the
file glob before invoking find.

In any case, the expansion in that location is data dependent and
depends upon the files in the directory.  It isn't robust.  In other
words, don't do it like that. :-)

The {} part is not special to the shell and does not need to be quoted.

> The above command failed when it encountered a filename beginning with
> "-", generating

The shell is doing the expansion of the !(*.iso) part.  That is
expanded before find is launched.  Then the result of the expansion is
behind handed to find as an option argument.  You can see what you are
telling find by using echo to do so.

  echo !(*.iso)

And then think about the result with find:

  echo find !(*.iso) -exec rm '{}' +

See that the files being expanded to may contain a leading dash and in
that case will be seen as an option to find.

> find: unknown predicate `-WWW.UNITED-FORUMS.CO.UK-.nfo'

Due to a file in your directory.  That is due to the shell expansion
before invoking find.

> Assuming find was interpreting the filename as an option, I tried
> hiding it behind -iname, as
> 
> find -iname !(*.iso) -exec rm -f {} +

Once you understand that the shell is doing the expansion and not find
then you will understand why neither of your cases are working as you
previously expected.  With that understanding your expectations will
be different and improved.  :-)

Try this for a find only implementation:

  find . ! -name '*.iso' -exec echo rm -f {} +

Or with GNU find extensions use the -delete option which is somewhat safer.

  find . ! -name '*.iso' -ls
  : find . ! -name '*.iso' -delete  < careful-here

I always test using either 'echo' or '-ls' first to make sure I am
deleting what I should be deleting.

Bob



reply via email to

[Prev in Thread] Current Thread [Next in Thread]