I'm trying to match relative paths using a PathMatcher. A very common case is to use a pattern like **/foo.php to match all files named foo.php whatever is the folder they are in.
But I found a behavior that look wrong to me, when the file is actually in no folders:
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.Paths;
public class PathMatcherTest {
public static void main(String[] args) {
testMatch("foo.php", Paths.get("foo.php"));
testMatch("foo.php", Paths.get("sub/foo.php"));
testMatch("**/foo.php", Paths.get("sub/foo.php"));
testMatch("**/foo.php", Paths.get("foo.php"));
}
private static void testMatch(String pattern, Path path) {
PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
if (pathMatcher.matches(path)) {
System.out.println(pattern + " matches " + path);
} else {
System.out.println(pattern + " doesn't matches " + path);
}
}
}
produces:
foo.php matches foo.php // OK foo.php doesn't matches sub/foo.php // OK **/foo.php matches sub/foo.php // OK **/foo.php doesn't matches foo.php // KO, why ????
Why is the GLOB pattern **/foo.php not matching foo.php? Am I misreading the spec, or is it a bug?
From the documentation:
The
**characters matches zero or more characters crossing directory boundaries.
With your pattern **/foo.php it's easy to see why it's not working. Because ** can be empty, the matcher essentially checks if foo.php matches /foo.php (which it clearly should not, one is located in the current folder, the other in the root).
To fix this: You can use a subpattern to match the case where the file resides in no folder. You can achieve this by changing your pattern to {foo.php,**/foo.php}
The
{ }characters are a group of subpatterns, where the group matches if any subpattern in the group matches. The "," character is used to separate the subpatterns. Groups cannot be nested.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With