什么时候可以通过文件glob()函数理解**?

4
在Java7中,sun.nio.fs.GlobsgetPathMatcher()似乎理解成语法**作为跨目录匹配零或多个字符的一种方式(参见getPathMatcher javadoc)。
我可以发誓,在某些合适的选项设置下,某些外壳(zsh、bash、tcsh)曾经给我提供过相同的行为。但是我无论如何也想不起来如何启用这个功能,我甚至开始怀疑自己是否在某个时候让它工作......(编辑:zsh提供了这种行为,但只针对目录,即"**.gz"不能匹配foo / bar/fubar.gz,但"**/*.gz"可以)。
事实上,在查看各种glob实现(例如POSIX glob(3)、glob(7)和Perl File :: Glob的文档)时,似乎没有提到这种行为。一个例外是Ruby的Dir.glob(),它明确地处理**
(原问题是:“有人知道如何在Unix shell(例如zsh)中启用此功能吗?”,但现在请参见下面的编辑问题)。
作为一个额外的问题:有人知道如何在Google中搜索'**'吗?...
编辑的问题 事实上,看起来我的zsh shell确实接受了这种行为(感谢回复者断言这一事实并促使我进一步查看)。我认为它不是因为以下微妙之处:"**.gz"不能匹配<path>/<prefix>.gz,但"**/*.gz"可以。以下是一个示例。让我们从以下树开始:
$ find . -type f | sort
./foo/a.gz
./foo/bar/fubar/abc.gz
./foo/bar/x.gz
./foo/bar/y.gz
./xyz.gz

"**.gz" 不匹配子目录中的内容,只匹配 "*.gz" 的内容:

$ ls -1 **.gz
xyz.gz

"**/*.gz"则表示:

$ ls -1 **/*.gz
foo/a.gz
foo/bar/fubar/abc.gz
foo/bar/x.gz
foo/bar/y.gz
xyz.gz

现在,将其与Java行为进行比较:
@Test
public void testStar() {
    String pat = Globs.toUnixRegexPattern("*.gz");
    assertEquals("^[^/]*\\.gz$", pat);
}

@Test
public void testStarStar() {
    // '**' allows any number of directories on the path
    // this apparently is not POSIX, although darn useful
    String pat = Globs.toUnixRegexPattern("**.gz");
    assertEquals("^.*\\.gz$", pat);
}

很明显(从正则表达式中可以看出),这里的"**"匹配路径上的任何字符(即在正则表达式中变成".*"),无论是在子目录中还是不在,也无论是作为文件名的一部分还是不是。

(免责声明: Globssun.nio.fs.Globs.toUnixRegexPattern(String glob)的一个副本,因为我需要一个跨平台的解决方案)。


2
zsh具有**递归通配符功能。据我所知,默认情况下已启用该功能。您需要使用setopt extendedglob来打开一些额外的通配符功能,但这不是其中之一。 - Alan Curry
1
好的,它对我不起作用。我一定以某种方式无意中禁用了它。在一个包含*.png文件和子目录的目录中,echo *.png | wc -wecho **.png | wc -w给出相同的结果。我尝试了extendedglob,但正如你所提到的,它并没有影响行为。 - Pierre D
它的zsh版本并不完全像那样工作。**匹配任意数量的目录,但要匹配末尾的文件,您必须单独指定它。echo **/*.png - Alan Curry
2个回答

5

POSIX shell 中:

路径名中的斜杠字符应该通过在模式中使用一个或多个斜杠来显式匹配; 它既不应该被星号或问号特殊字符匹配,也不应该被方括号表达式匹配

您可以谷歌搜索:"文件名扩展模式"。

在bash中,您可以设置globstar

[星号]匹配任何字符串,包括空字符串。当启用globstar shell选项,并且在文件名扩展上下文中使用'*'时,两个相邻的'*'将作为单个模式匹配所有文件和零个或多个目录和子目录。如果跟随一个'/',则两个相邻的'*'仅匹配目录和子目录。

$ shopt -s globstar
$ ls **/
$ shopt -u globstar
$ ls **/

注意:此处使用“/”仅用于显示目录。

4

**在Zsh的扩展 glob 语法中被解释为(*/)#(零个或多个目录),这是由 Zsh 特定的 C 代码 (Src/glob.c) 实现的。这种行为不是可选的。

当在 Bash 中启用 shopt -s globstar 时,它会在 Bash 的扩展 glob 语法中类似地工作,这是由 Bash 特定的 C 代码 (pathexp.c) 实现的。默认情况下此功能处于关闭状态。

在传统的 UNIX glob 中,** 被解释为与 * 相同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接