Java PathMatcher:为什么 ** 不适用于零文件夹?

问题描述

我正在尝试使用 PathMatcher 匹配相对路径。一个非常常见的情况是使用 **/foo.PHP 之类的模式来匹配所有名为 foo.PHP文件,无论它们位于哪个文件夹中。 但是当文件实际上不在文件夹中时,我发现了一种对我来说看起来不对的行为:

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("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);
    }
  }

}

产生:

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 ????

为什么 GLOB 模式 **/foo.PHPfoo.PHP 不匹配?是我误读了规范,还是一个错误

解决方法

来自documentation

** 字符匹配零个或多个跨越目录边界的字符。

使用您的模式 **/foo.php 很容易看出为什么它不起作用。因为 ** 可以为空,所以匹配器本质上会检查 foo.php 是否匹配 /foo.php(显然不应该,一个位于当前文件夹中,另一个位于根目录中)。>

要解决此问题:您可以使用子模式来匹配文件不位于任何文件夹中的情况。您可以通过将模式更改为 {foo.php,**/foo.php}

来实现此目的

{ } 字符是一组子模式,如果组中的任何子模式匹配,则该组匹配。 “,”字符用于分隔子模式。组不能嵌套。