4

在 Java7 中,sun.nio.fs.Globs似乎getPathMatcher()将成语理解**为一种跨目录边界匹配零个或多个字符的方法(请参阅getPathMatcher javadoc)。

我可以发誓一些适当的选项设置的shell(zsh,bash,tcsh)在某些时候给了我相同的行为。但是对于我的一生,我不记得如何启用它,我什至开始怀疑我的记忆是否我在某个时候工作过......(编辑:zsh 提供了这种行为,但仅适用于目录,即"**.gz"不'不匹配foo/bar/fubar.gz,但"**/*.gz"确实如此)。

事实上,查看各种 glob 实现的文档(例如 POSIX glob(3)、glob(7) 和 Perl 的 File::Glob)似乎并没有在任何地方提到这种行为。一个例外是 RubyDir.glob()显式处理**.

(最初的问题是:“有人知道如何在 unix shell(例如 zsh)中启用此行为吗?”,但现在请参阅下面的已编辑问题)。

作为一个额外的问题:有人知道如何'**'在 Google 中搜索吗?...


已编辑的问题

事实上,我的 shell 似乎确实接受了这种行为zsh(感谢断言这一事实​​并促使我进一步研究的响应)。我认为它不匹配的原因来自以下微妙之处:"**.gz"不会匹配 a <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);
}

显然(从正则表达式),这里"**"匹配路径上的任何字符(即它变成".*"正则表达式),无论是否在子目录中,以及是否作为文件名的一部分。

(免责声明:Globs是一个副本,sun.nio.fs.Globs.toUnixRegexPattern(String glob)因为我需要跨平台的东西)。

4

2 回答 2

5
于 2012-08-15T18:51:40.247 回答
4

** is interpreted as (*/)# (zero or more directories) in Zsh's extended glob syntax, which is implemented in Zsh-specific C code (Src/glob.c). This behavior is not optional.

When shopt -s globstar is enabled in Bash, it acts similarly in Bash's extended glob syntax, which is implemented in Bash-specific C code (pathexp.c). This is off by default.

In traditional UNIX glob, ** is interpreted the same as *.

于 2012-08-15T18:54:28.997 回答