什么时候文件glob()理解**?

时间:2012-08-15 17:34:30

标签: shell glob

在Java7中,sun.nio.fs.GlobsgetPathMatcher()似乎将习语**理解为跨目录边界匹配零个或多个字符的方式(请参阅{{ 3}})。

我可以发誓一些shell(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&#34;将:

$ 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);
}

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

(免责声明:Globssun.nio.fs.Globs.toUnixRegexPattern(String glob)的副本,因为我需要跨平台工作的内容。

2 个答案:

答案 0 :(得分:5)

POSIX shell中:

  

路径名中的斜杠字符应使用明确匹配   图案中有一个或多个斜杠;它不应该被匹配   星号或问号特殊字符也不用括号   表达

你可以谷歌:“文件名扩展模式”。

在bash中,您可以设置globstar

  

[星号]匹配任何字符串,包括空字符串。当globstar shell   选项已启用,‘*’用于文件名扩展上下文,   用作单个模式的两个相邻‘*’将匹配所有文件和   零个或多个目录和子目录。如果后跟一个'/',两个   相邻‘*’ s只匹配目录和子目录。

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

注意:此处使用'/'仅显示目录。

答案 1 :(得分:3)

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

在Bash中启用shopt -s globstar时,它在Bash的扩展glob语法中的行为类似,它以Bash特定的C代码(pathexp.c)实现。默认情况下这是关闭的。

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