home | list info | list archive | date index | thread index

Re: [OCLUG-Tech] Odd behaviour in find

On 15-11-25 04:52 PM, Alex Pilon wrote:
>>> What's odd is that `find -xdev -- foo` doesn't work, yet `find --
>>> foo` does. I expected -- to be properly interpreted as the end of
>>> options indicator, as per the manual.
>>
>> In the case 'find -xdev --' the '--' is coming after the first
>> expression because '-xdev' is a predicate.
>>
>> In the case 'find -- foo' the '--' is coming before the first
>> expression because 'foo' is a path.
>>
>> This is entirely consistent with the manual.  The optional '--' just
>> has to come before the first expression if something that could be
>> ambiguously interpreted as an option is an argument to an expression.
> 
> That's what I'm doing…
> 
>     $ touch ./-f
>     $ find -- -f
>     find: unknown predicate `-f'
> 
> So let's double-check the man page.
> 
> find(1):
>     A double dash -- can also be used to signal that any remaining
>     arguments are not options
> 
> So the remainder are treated as expressions, "real options", or paths?
> I'd have thought that the remainder would be treated as paths. Are you
> saying that they're treated as expressions (like -name, -whatever as
> long as it isn't -H and friends)?

Yes, that's exactly it.

Anything after the '--' is treated as a path or an expression.  Paths must come before expressions.  Expressions start
with a predicate.

> find(1):
>     (though ensuring that all start points
>     begin with either `./' or `/' is generally safer if you use
>     wildcards in the list of start points).
> 
> This parenthesis would make me think that the remaining get treated as
> paths, not expressions. I can do what this says, nearly trivially, but
> that just seems wrong.

The parenthetical is talking about globbing behaviour of the shell.

> I just wanted to protect any paths passed through to find in the code
> below.
> 
>     diff --git a/pax b/pax
>     index 9b7de7d..dae4555 100755
>     --- a/pax
>     +++ b/pax
>     @@ -78,7 +88,9 @@ if args.mode == 'write':
>          if args.x is None:
>              bsdcpio_args += ['-H', 'pax']
>          if len(args.args) > 0:
>     -        find = subprocess.Popen(['find', '--'] + args.args, stdout=subprocess.PIPE)
>     +        find_args = ['-xdev'] if args.X else []
>     +        find = subprocess.Popen(['find'] + find_args + ['--'] + args.args,
>     +                                stdout=subprocess.PIPE)
>              bsdcpio_stdin = find.stdout
>      else:
>          bsdcpio_stdin = None
> 
> I suppose that I could just use a list comprehension but that wouldn't
> be the perfect and simplest way.
> 
> I just wanted -xdev to be unambiguously an expression, -- treated as the
> options delimiter, and everything after a path.

The usage of the Unix 'find' command is this.

  find [options] [paths] [expressions]

All paths must come before all expressions.  What it doesn't say is options can be intermixed with paths and
expressions, which can lead to ambiguity.

-- 
Stephen M. Webb  <stephen [ dot ] webb [ at ] bregmasoft [ dot ] ca>