Why does glob pattern with double asterisk not match anything in subdirectories?
I’m trying to write a
.gitignore rule to exclude some files in a particular directory that has multiple levels of subdirectories.
The folder structure looks something like this:
- git: How do I recursively add all files in a directory subtree that match a glob pattern?
- git log for commits matching branch or tag glob
- staging all files except specific files using glob patterns in git
- Git Glob syntax: ignoring files everywhere or in a specific folder
- Difference between ** and * in glob matching (.gitignore)
- Recursively add files by pattern
out ├─a │ ├─source │ │ ├─.keepme │ │ ├─183597.txt │ │ ├─271129.txt │ │ └─288833.txt │ └─parsed │ ├─.keepme │ ├─183597.csv │ ├─271129.csv │ └─288833.csv ├─b │ └─(...) (etc.)
I would like to keep the
.keepme files (so that Git saves the directory structure), so I figure I’ll write a rule to match anything under
out that matches the pattern
However, this does not match any files.
I thought that
** will match any number of subdirectories; why is this not working?
I’m running Git 1.8 in Bash 4.2 on a Fedora 18 VM.
2 Solutions collect form web for “Why does glob pattern with double asterisk not match anything in subdirectories?”
First, make sure you are using Git 1.8.2 or up, since that’s when
** support was introduced.
It sounds like you’re trying to exclude
.keepme files by matching
*.*. However, since
* matches zero or more characters, it matches the empty string in front of the period in
.keepme, including this file as well.
Maybe you intended it to work like
If you’d like to match all non-dotfiles, you can use
out/**/[!.]* which will also include filenames without periods in them, like
I think that other guy’s answer is a good lead. The pattern
out/**/[!.]*.*, which should match everything that contains a period and does not start with a period, also works in my test in bash, Arch Linux:
$ find * -type f out/a/source/4232352.txt out/a/source/1312312.txt out/a/source/4234234.txt out/a/source/.keepme out/a/parsed/1231222.csv out/a/parsed/9593343.csv out/a/parsed/5675675.csv out/a/parsed/.keepme $ cat .gitignore out/**/[!.]*.* $ git init && git add -A && git status --ignored # On branch master # # Initial commit # # Changes to be committed: # (use "git rm --cached <file>..." to unstage) # # new file: .gitignore # new file: out/a/parsed/.keepme # new file: out/a/source/.keepme # # Ignored files: # (use "git add -f <file>..." to include in what will be committed) # # out/a/parsed/1231222.csv # out/a/parsed/5675675.csv # out/a/parsed/9593343.csv # out/a/source/1312312.txt # out/a/source/4232352.txt # out/a/source/4234234.txt
EDIT: It seems this actually doesn’t work in the git bash bundled with the Windows version of git, there none of the above files are ignored by this