When constructing a pattern that matches a file name such as /home/user/project/.git
, how does one match the .
character "explicitly" -- that is, without the use of shopt -s dotglob
?
The manual at https://www.gnu.org/software/bash/manual/html_node/Filename-Expansion.html states:
When a pattern is used for filename expansion, the character ‘.’ at the start of a filename or immediately following a slash must be matched explicitly, unless the shell option dotglob is set.
What, exactly, does it mean, to "be matched explicitly"?
And again, at http://www.tldp.org/LDP/abs/html/globbingref.html (in the Notes
section at the end), the same notion is addressed:
Filename expansion can match dotfiles, but only if the pattern explicitly includes the dot as a literal character.
The note provides the following examples:
~/[.]bashrc # Will not expand to ~/.bashrc
~/?bashrc # Neither will this.
# Wild cards and metacharacters will NOT
#+ expand to a dot in globbing.
~/.[b]ashrc # Will expand to ~/.bashrc
~/.ba?hrc # Likewise.
~/.bashr* # Likewise.
I fail to understand the inner workings of the last three examples, which will expand to include the "dotfile".
How, specifically, does placing the b
in brackets after the .
make this an "explicit" match in the example ~/.[b]ashrc
? The subsequent examples are even more ambiguous to me. I simply fail to understand how manipulating the pattern in ways that seem completely unrelated to the .
character cause the pattern to produce a match.
With regard to why I would like to avoid using shopt -s dotglob
, the impetus for this question is rooted in the fact that I am writing these patterns for use in another program's configuration file. I want to exclude paths that contain, for example, "hidden .git
directories", and I'm not sure that I have the ability to specify dotglob
in any capacity.
In essence: What is the simplest means by which to match the .
character by "being explicit"? Placing the next character in brackets "makes it work", but I'd like to know why; I feel like I'm "shooting in the dark" with that approach.
Any explanation as to the underlying behavior in this regard is much appreciated.
EDIT TO ADD:
Initially, it didn't seem relevant, but because people seem to be interested in the specifics of my use-case, I'll explain further.
I'm using a Host-Based Intrusion Detection software called Samhain
. Samhain will "alert" whenever the filesystem is modified according to certain user-specified configuration parameters.
I don't want Samhain to alert when files within .git
directories (that are located within certain parent directories) are created/modified/deleted. In Samhain, this type of exclusion is performed by defining "ignore rules". The exact specification of these rules is explained at http://www.la-samhna.de/samhain/manual/filedef.html , in 4.2. File/directory specification
.
In short:
Wildcard patterns ('*', '?', '[...]') as in shell globbing are supported for paths. The leading '/' is mandatory.
So, I am trying to write an "ignore rule" that will match the .git
directories in question, which will, in effect, cause Samhain to exclude them from its monitoring activities.
Initially, I tried this:
[IgnoreAll]
dir = -1/home/user/project/*/*/.git
This didn't work; Samhain still alerted whenever files inside those .git
directories changed.
Upon finding the examples cited above, I tried this:
dir = -1/home/user/project/*/*/.[g]it
With this change, Samhain ignores the files, as desired.
In posting this question, I was simply trying to understand why that change has the intended effect.
I will say, I feel less stupid given that the very pattern I was trying to use at first does indeed match the .git
directories in question when I use "echo" test:
echo /home/user/project/*/*/.git
So, it wasn't so much that I was misunderstanding something fundamental with regard to pattern-matching, globbing, or file-name expansion in Bash; to the contrary, there seem to be nuances with regard to how Samhain, in particular, implements pattern-matching in this context.
I have no idea why this doesn't work when applied in the context of Samhain's configuration file (obviously). Maybe somebody will be able to explain, given this edit.
.
to be found, whatever the rest if it matches.Ignore
directive.” See my updated answer.