何时在 JAVA 的 glob 语法中使用 **(双星)

Posted

技术标签:

【中文标题】何时在 JAVA 的 glob 语法中使用 **(双星)【英文标题】:When to use ** (double star) in glob syntax within JAVA 【发布时间】:2013-09-14 08:56:50 【问题描述】:

直接来自thisJava Oracle 教程:

两个星号 ** 与 * 类似,但跨越目录边界。这 语法一般用于匹配完整路径。

任何人都可以做一个真实的例子吗? “跨越目录边界”是什么意思? 跨越目录边界,我想像检查文件从根到getNameCount()-1。 在 practice 中再举一个真实的例子来解释 * 和 ** 之间的区别会很棒。

【问题讨论】:

表示会递归遍历所有子目录,其中*只会从当前目录抓取文件,忽略子目录 【参考方案1】:

FileSystem#getPathMatcher() 的 javadoc 有一些很好的例子和解释

*.java Matches a path that represents a file name ending in .java 
*.*    Matches file names containing a dot 

*.java,class  Matches file names ending with .java or .class 
foo.?           Matches file names starting with foo. and a single character extension 
/home/*/*       Matches /home/gus/data on UNIX platforms 
/home/**        Matches /home/gus and /home/gus/data on UNIX platforms 
C:\\*           Matches C:\foo and C:\bar on the Windows platform (note that the backslash is escaped; as a string literal in the Java Language the pattern would be "C:\\\\*")  

所以/home/** 会匹配/home/gus/data,但/home/* 不会。

/home/* 直接表示/home 目录中的每个文件。

/home/** 表示/home 内任何目录中的每个文件。


*** 的示例。假设你当前的工作目录是/Users/username/workspace/myproject,那么下面只会匹配./myproject文件(目录)。

PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:/Users/username/workspace/*");
Files.walk(Paths.get(".")).forEach((path) -> 
    path = path.toAbsolutePath().normalize();
    System.out.print("Path: " + path + " ");
    if (pathMatcher.matches(path)) 
        System.out.print("matched");
    
    System.out.println();
);

如果您使用**,它将匹配该目录中的所有文件夹和文件。

【讨论】:

【参考方案2】:

双星号 (**) 匹配多个嵌套目录中的零个或多个字符。在解释主要概念后,我将通过示例逐步解释双星号以及其他有用的通配符。


通配符

glob 是用于匹配文件路径的字符串文字和/或通配符。使用一个或多个 glob 在文件系统上定位文件称为 globbing。 globbing 不仅限于 Java。它还用于匹配各种配置文件中的文件,例如在Git中列出.gitignore中被忽略的文件和目录,在Unix操作系统中选择文件和文件夹,例如ls **/*.java等。

以下是通配符最重要的部分。双星号(**)就是其中之一:


分隔符和段 (/)

在 Globbing 中,正斜杠字符 (/) 始终充当 分隔符,无论使用什么操作系统。 segment 是两个分隔符之间的所有内容。

示例:tests/HelloWorld.java

这里,testsHelloWorld.java 是分段,/ 是分隔符。


单星号 (*)

单个星号 (*) 匹配 一个 段中的零个或多个字符。它用于对一个目录中的文件进行通配。

示例:*.java

此 glob 将匹配 HelloWorld.java 等文件,但不匹配 tests/HelloWorld.javatests/ui/HelloWorld.java 等文件。


双星号 (**)

双星号 (**) 匹配 多个 段中的零个或多个字符。它用于对嵌套目录中的文件进行通配。

示例:tests/**/*.java

在这里,文件选择将被限制在tests 目录中。 glob 将匹配 tests/HelloWorld.javatests/ui/HelloWorld.javatests/ui/feature1/HelloWorld.java 等文件。


问号(?)

问号(?) 匹配一个段中的单个字符。可用于匹配名称仅相差一个字符的文件或文件夹。

示例:tests/?at.java

这将匹配tests/cat.javatest/Cat.javatest/bat.java 等文件。


方括号 ([abc])

方括号 ([...]) 匹配方括号中给出的单个字符。

示例:tests/[CB]at.java

此 glob 将匹配 tests/Cat.javatests/Bat.java 等文件


方括号范围 ([a-z])

方括号范围 ([a-z]),匹配范围内给定的一个字符。

示例:tests/feature[1-9]/HelloWorld.java

此 glob 将匹配 tests/feature1/HelloWorld.javatest/feature2/HelloWorld.java 等文件...直到 9


否定 (!)

否定(!)用于排除某些文件。

示例:tests/[!C]at.java

这将排除文件tests/Cat.java,并将匹配tests/Bat.javatests/bat.javatests/cat.java等文件。


就是这样!希望对您有所帮助。

【讨论】:

以上是关于何时在 JAVA 的 glob 语法中使用 **(双星)的主要内容,如果未能解决你的问题,请参考以下文章

为啥 cmake 文件 GLOB 是邪恶的?

在 Unix/Linux/Java 世界中,GLOB 的缩写是啥?

SQLite语法

“glob”类型模式是不是有等效的 java.util.regex ?

.gitignore格式说明详解

从 glob 表达式创建正则表达式