bug-findutils
[Top][All Lists]
Advanced

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

Re: Filename Expansion: Find Utility Pattern Matching vs Bash Shell Patt


From: Assaf Gordon
Subject: Re: Filename Expansion: Find Utility Pattern Matching vs Bash Shell Pattern Matching
Date: Wed, 17 Jun 2015 13:49:17 -0400
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0

Hello Michael,

On 06/17/2015 12:43 PM, Michael Convey wrote:
<...>
I'm trying to understand why
the operators work differently under different circumstances. For example,
according to the following link, 'find -name' appears to use fnmatch(),
whereas bash appears to use glob():

I believe this is a technical issue, not a conceptual one.

fnmatch(3) 
[http://pubs.opengroup.org/onlinepubs/9699919799/functions/fnmatch.html]
checks a pattern (e.g. "*.txt") against a string (i.e. "const char*" in C).
by itself, it does not do any disk access, and works independently of any 
existing files.

glob(3) [http://pubs.opengroup.org/onlinepubs/9699919799/functions/glob.html]
compares a pattern (e.g. "*.txt") against existing files in the current 
directory.
Internally, it uses fnmatch() (at least in glibc implementation, which you can 
see here:
https://sourceware.org/git/?p=glibc.git;a=blob;f=posix/glob.c;h=d65e55dcd62fe465de8fa2b64cf7b37bb0e8068c;hb=HEAD#l1607
 ).

Bash can use 'glob(3)' because when you specify a pattern, you want to get as a 
result all the files in the current directory.
Find can not use 'glob(3)', because by the time you've used the "-name" 
predicate, it could very well be limited to only a subset of the files in the current 
directory.


For example:
    $ touch a1 a2 a3 a4
    $ mkdir a5

    # bash will return *all* matches, including the directory:
    $ ls -d a*
    a1  a2  a3  a4  a5

    # But find might be restricted to a subset of files,
    # in this example, the name is checked only on files, not directories:
    $ find . -type d -name "a*"

So from an implementation POV, find must get the file list independently, then 
call fnmatch on each filename (as a string),
instead of using glob. See GNU find's "-name" implementation here:
 http://git.savannah.gnu.org/cgit/findutils.git/tree/find/pred.c#n530


HTH,
 - assaf

disclaimer: this explanation is my opinion, I hope it's correct, but there's no 
guarantee :)



reply via email to

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