ripgrep 11.0.2
-SIMD -AVX (compiled)
+SIMD +AVX (runtime)
brew install ripgrep
macos 10.5.1
NB: There have been questions around this topic before, but I haven't been able to find the answer in past issues. Apologies if I missed something!
rg -g '*glob*' does not match against filespaths of any depth
In plain english, I want to search files whose path contains foo and whose content contains the pattern .*bar$
My understanding is that I should be able to accomplish this with
rg -g '*foo*' .*bar$
As a concrete example (though I've removed the code and only returned result counts)
rg -g '*ulia*' titleize\|titlecase | wc -l
# => 0
^ I expect to get 3. I can achieve this with the following:
rg --files | rg ulia | xargs rg -l titleize\|titlecase | wc -l
# => 3
I think I expect the globbing to work somewhat similarly to the ag interface, e.g.
ag -G ulia "titleize|titlecase"
Perhaps I don't understand how unix globs work with nested file paths.
Thanks for your time!
Possibly related: https://github.com/BurntSushi/ripgrep/issues/1442
More details in the docs for globs would be great!
Thanks for the report. Unfortunately, I don't think I see a reproducible test case here. Just trying in the ripgrep repo seems to work just fine:
$ rg fixed-strings -g '*args*'
src/args.rs
690: if self.is_present("fixed-strings") {
1366: /// Note that if -F/--fixed-strings is set, then all patterns will be
1420: /// if -F/--fixed-strings is set.
1429: /// if -F/--fixed-strings is set.
1456: /// -F/--fixed-strings flag is set. Otherwise, the pattern is returned
1459: if self.is_present("fixed-strings") {
I think what I'm looking for is directory matches as well. Using the source tree again:
( A )
==$ rg -l -g '*src*' LineIter | wc -l
0
( B )
==$ rg --files | rg src | xargs rg -l LineIter | wc -l
4
I think (A) is not how you intend rg to be used, or at least not in order to achieve (B). But I think this is a common mistake for folks coming from ag. I'm hoping to better understand how to achieve something like (B) with the -g flag.
@wcpines Ah I see. The key thing you're missing is that, in globs, wildcards like * often do not match path separators such as /. You can see that grep behaves the same:
$ grep -r LineIter -l --include '*src*'
$
Usually, the way to do what you want is with recursive globs:
$ rg LineIter -l -g '**/src/**'
grep-printer/src/util.rs
grep-searcher/src/sink.rs
grep-searcher/src/lib.rs
grep-searcher/src/lines.rs
Where **/src/** basically says, "match any file path where src is a component in that path."
For ag, it uses regexes, which often do not have the same "wildcards do not match path separators" restriction. ripgrep does not support filtering files via regex. So if you want that, then you'll want to use xargs.
If it's part of the path OR the filename, my understanding is to either
-g '*src*' -g '**/src/**')Is this correct?
Also, thanks so much for your time and help here. (Feel free to close this issue out!)
@wcpines Almost. Just -g '**/src/**' is enough, since that will match a file named src. The key is that **/src/** matches any path that has src as part of its name. If you want to write a glob that matches src literally anywhere, e.g., even in foo/foosrcfoo/foo, then I guess you would need **/*src*/**.
Thanks again!
@wcpines Almost. Just
-g '**/src/**'is enough, since that will match a file namedsrc. The key is that**/src/**matches any path that hassrcas part of its name.
@BurntSushi The glob works with -g but not when added as a type using --type-add. Is there a way to add as a type?
% mkdir -p foo/{src,test}
% echo "hello" > foo/src/main.c
% echo "hello" > foo/test/main.c
% rg -g "**/src/**" hello
foo/src/main.c
1:hello
% rg hello
foo/test/main.c
1:hello
foo/src/main.c
1:hello
% rg --type-add "src:**/src/**" -t src hello
%
@balki Yes, that is intended behavior. "file types" don't apply to directories: https://github.com/BurntSushi/ripgrep/blob/98de8d248a677bbdb5ab46f53a58ceabbc24a2df/ignore/src/types.rs#L503-L507
Most helpful comment
@wcpines Almost. Just
-g '**/src/**'is enough, since that will match a file namedsrc. The key is that**/src/**matches any path that hassrcas part of its name. If you want to write a glob that matchessrcliterally anywhere, e.g., even infoo/foosrcfoo/foo, then I guess you would need**/*src*/**.