[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 :)