You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java与Python双星号glob模式匹配差异及Java适配方案问询

Glob模式跨语言匹配差异问题解答

测试目录结构

测试使用的标准目录结构如下:

Tests
│─── HelloWorld.java
│
└── ui
    │── HelloWorld.java
│
    └── feature1
        │── HelloWorld.java

复现现象

使用如下Java代码执行glob路径匹配:

import java.nio.file.*;

public class Test{
    public static void main(String[] args) throws Exception {
        PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:" + "Tests/**/*.java");
        Path base = Paths.get(".").toAbsolutePath();
        Files.walk(base).forEach((path) -> {
            path = base.relativize(path);
            if (pathMatcher.matches(path)) {
                System.out.println(path);
            }
        });
    }
}

代码执行后仅匹配到2个文件:

Tests\ui\feature1\HelloWorld.java
Tests\ui\HelloWorld.java

Tests根目录下的Tests/HelloWorld.java未被匹配。
使用相同模式在Python中执行匹配验证:

>>> import glob
>>> glob.glob('Tests/**/*.java', recursive=True)
['Tests\\HelloWorld.java', 'Tests\\ui\\HelloWorld.java', 'Tests\\ui\\feature1\\HelloWorld.java']

Python可正确匹配全部3个.java文件。

1. 匹配结果差异的核心原因

差异来自两门语言对glob通配符**的实现规则不同:

  • Java实现规则:Java NIO默认PathMatcher的glob规则明确规定,仅当**作为模式的最后一个路径段时,才允许匹配零层目录;如果**位于模式中间(即后面还跟有其他路径段),必须匹配至少一层目录。示例中使用的模式Tests/**/*.java中,**后面还有*.java段,属于中间位置,因此要求Tests目录和目标java文件之间必须存在至少一级子目录,直接放在Tests根目录下的HelloWorld.java因为中间没有子目录层级,无法被匹配。
  • Python实现规则:Python的glob模块在开启recursive=True时,不对**的位置做限制,无论**在模式哪个位置,都可以匹配零层或多层目录,因此Tests/**/*.java可以直接命中Tests根目录下的java文件。

2. 不修改匹配模式的Java代码调整方案

核心思路是:在不改动Tests/**/*.java模式串的前提下,对传给匹配器的待匹配路径做无副作用的格式调整,给中间的**补一个可被匹配的合法路径段.(代表当前目录,属于文件系统认可的空目录占位,不会改变路径指向的实际文件),让所有Tests目录下的java文件都满足**至少匹配一个段的要求。
调整后的可运行代码如下:

import java.nio.file.*;

public class Test{
    public static void main(String[] args) throws Exception {
        PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:" + "Tests/**/*.java");
        Path base = Paths.get(".").toAbsolutePath();
        Path testDirPrefix = Paths.get("Tests");
        Files.walk(base).forEach((path) -> {
            Path relativePath = base.relativize(path);
            // 跳过Tests目录外的无关路径
            if (!relativePath.startsWith(testDirPrefix)) {
                return;
            }
            // 构造带.段的匹配专用路径,不改变原文件指向
            Path matchPath = testDirPrefix.resolve(".").resolve(relativePath.subpath(1, relativePath.getNameCount()));
            if (pathMatcher.matches(matchPath)) {
                System.out.println(relativePath);
            }
        });
    }
}

运行以上代码可以正确匹配全部3个java文件,与Python执行结果一致。

内容的提问来源于stack exchange,提问作者Mikhail Bolotov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 09:27:27