Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Globstar doesn't match zero directories #88

Closed
mmxmb opened this issue Oct 16, 2023 · 4 comments
Closed

Globstar doesn't match zero directories #88

mmxmb opened this issue Oct 16, 2023 · 4 comments
Assignees
Labels

Comments

@mmxmb
Copy link
Contributor

mmxmb commented Oct 16, 2023

Issue description

I expect a/**/ to match a directory a but doublestar.Match returns false:

import (
	"fmt"

	"github.com/bmatcuk/doublestar/v4"
)

func main() {
	match1, err := doublestar.Match("a/**/", "a")
	if err != nil {
		panic(err)
	}
	match2, err := doublestar.Match("a/**/", "a/")
	if err != nil {
		panic(err)
	}
	fmt.Printf("a/**/ matches a: %t\n", match1)
	fmt.Printf("a/**/ matches a/: %t\n", match2)
}

Running this returns:

› go run main.go
a/**/ matches a: false
a/**/ matches a/: false

I understand that it's ambiguous whether a by itself is a regular file or a directory, therefore I am also trying to match a/.

I assume that this project is attempting to replicate Bash globstar functionality, so here's my attempt at doing the same in Bash 5.2:

bash-5.2$ bash --version
GNU bash, version 5.2.15(1)-release (aarch64-apple-darwin23.0.0)
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
bash-5.2$ mkdir a
bash-5.2$ shopt -s globstar
bash-5.2$ ls -d a/**/
a/

Bash shopt docs confirm that this is the intended behavior:

globstar
If set, the pattern ‘**’ used in a filename expansion context will match all files and zero or more directories and subdirectories. If the pattern is followed by a ‘/’, only directories and subdirectories match.

In this example, I am trying to match zero directories, or subdirectories.

Question

Can you please confirm whether this is an oversight in doublestar.Match implementation and check whether it's possible to correct this behavior?

Versions

I am using go1.21.3 and bmatcuk/doublestar/v4 v4.6.0.

@mmxmb mmxmb changed the title Globstar doesn't match the directory at 0th depth Globstar doesn't match zero directories Oct 16, 2023
@mmxmb
Copy link
Contributor Author

mmxmb commented Oct 18, 2023

I was able to fix this behavior by changing one line in match.go:

@@ -303,7 +301,7 @@ MATCH:
 func isZeroLengthPattern(pattern string, separator rune) (ret bool, err error) {
        // `/**` is a special case - a pattern such as `path/to/a/**` *should* match
        // `path/to/a` because `a` might be a directory
-       if pattern == "" || pattern == "*" || pattern == "**" || pattern == string(separator)+"**" {
+       if pattern == "" || pattern == "*" || pattern == "**" || pattern == string(separator)+"**" || pattern == string(separator)+"**"+string(separator) {
                return true, nil
        }

All existing test cases still pass and here's a new test case that passes after this change is made:

	{"a/**/", "a", true, true, nil, false, false, false, true, 1, 1},

Are there any concerns about opening a PR with this change?

@bmatcuk bmatcuk self-assigned this Oct 18, 2023
@bmatcuk bmatcuk added the bug label Oct 18, 2023
@bmatcuk
Copy link
Owner

bmatcuk commented Oct 18, 2023

Hey @mmxmb - ya, go ahead and open a PR =) That sounds right to me, but I'll take a closer look over the weekend.

@mmxmb
Copy link
Contributor Author

mmxmb commented Oct 18, 2023

Thanks! Opened a PR: #89

@bmatcuk
Copy link
Owner

bmatcuk commented Oct 21, 2023

Merged! Thanks =)

@bmatcuk bmatcuk closed this as completed Oct 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants