gobwas / glob

Go glob
MIT License
948 stars 63 forks source link

Error in ** matching? #20

Closed virtuald closed 7 years ago

virtuald commented 7 years ago

Using the following test program:

package main

import (
    "fmt"
    "os"

    "github.com/gobwas/glob"    
)

func main() {

    pattern := os.Args[1]
    s := os.Args[2]

    g, err := glob.Compile(pattern, '/')
    if err != nil {
        fmt.Printf("glob: %s\n", err)
        os.Exit(1)
    }

    fmt.Printf("`%s` matches `%s`? %t\n", s, pattern, g.Match(s))
}

I get some strange results:

$ go run main.go 'test/**' test/foo.cs
`test/foo.cs` matches `test/**`? true

$ go run main.go 'test/**/*.cs' test/foo.cs
`test/foo.cs` matches `test/**/*.cs`? false

$ go run main.go 'test/**/*.cs' test/bar/foo.cs
`test/bar/foo.cs` matches `test/**/*.cs`? true

$ go run main.go 'test/**/*' test/foo.cs
`test/foo.cs` matches `test/**/*`? false

I would have expected all of the patterns to match as ** generally matches 0 or more subcomponents, but it seems like ** is only matching 1 or more subcomponents? Is this the intended behavior?

calmh commented 7 years ago

This matches what bash does, at least. I would say that even if ** matches zero or more components, the extra slash is relevant.

jb@unu:~/tmp $ shopt -s nullglob
jb@unu:~/tmp $ tree test
quux.txt
foo/
   bar.txt
jb@unu:~/tmp $ echo test/**/*.txt
test/foo/bar.txt
jb@unu:~/tmp $ echo test/**/*
test/foo/bar.txt
jb@unu:~/tmp $ echo test/**/quux.txt

jb@unu:~/tmp $ 
virtuald commented 7 years ago

Hm, I was thinking of the globstar option (which seems to match the way Java glob matches ** also):

$ shopt -s globstar
$ tree test
test
├── foo
│   └── bar.txt
└── quux.txt

1 directory, 2 files
$ echo test/**/*.txt
test/foo/bar.txt test/quux.txt
$ echo test/**/*
test/foo test/foo/bar.txt test/quux.txt
$ echo test/**/quux.txt
test/quux.txt
virtuald commented 7 years ago

For reference, the java docs I was thinking of: https://docs.oracle.com/javase/7/docs/api/java/nio/file/FileSystem.html#getPathMatcher(java.lang.String)

calmh commented 7 years ago

You're right, my test is meaningless as my bash treats ** the same as * and the test doesn't make that visible. Please ignore.

gobwas commented 7 years ago

Hi @virtuald! At first glance there no error? From readme:

Syntax is inspired by standard wildcards, except that ** is aka super-asterisk, that do not sensitive for separators.

** matches any symbols with given set of delimiters (in your program it is a slash '/'). Seems that with that meaning all matches are correct?

virtuald commented 7 years ago

@gobwas I was expecting the behavior to match the way it commonly seems to be implemented -- namely, the bash globstar option (see above), Java's getPathMatcher, and the golang doublestar library.

If the behavior doesn't match that, then it would be good to add additional documentation/examples clarifying what ** matches and (more importantly) what it does not match, and that it doesn't behave the same way as the other implementations named above.