在哪里可以找到“*/”在 Bash 或 Zsh 中的含义的明确答案?

在哪里可以找到“*/”在 Bash 或 Zsh 中的含义的明确答案?

我试图查看 O'Reilly 的一些关于 Unix 和 Bash 的参考资料,了解 的含义,*/但找不到任何内容。我们可以echo */看到所有的目录。

看起来它只意味着所有“目录”,而*意味着“所有文件和目录”,但由于某种原因,许多用户似乎不知道它,书籍也没有提到它。

是否有明确的资料来源谈论其*/含义及其变体?

答案1

POSIX规范是有关 UNIX 工具应如何表现的权威参考。这关于路径名解析的部分解释文件名中尾部斜杠的含义。

至少包含一个非 <slash> 字符且以一个或多个尾随 <slash> 字符结尾的路径名不得成功解析,除非尾随 <slash> 字符之前的最后一个路径名组件指定现有目录或目录条目这是在解析路径名后立即为目录创建的。

换句话说:foo/需要foo是现有目录,或者程序将创建的目录(因此mkdir foo/是允许的)。如果foo是其他类型的文件(常规文件、管道名称等),则访问它肯定foo/不起作用。

上面的句子不完整:foo/实际上是引用目录符号链接的有效方法。具体如下:

如果在路径名解析期间遇到符号链接,则行为应取决于路径名组件是否位于路径名末尾以及正在执行的功能。如果以下所有条件均成立,则路径名解析完成:

1. 这是路径名的最后一个路径名组成部分。 2. 路径名没有尾随 . 3. 要求函数作用于符号链接本身,或者某些参数指示函数作用于符号链接本身。

在所有其他情况下,系统应使用符号链接 (...) 的内容为剩余路径名(如果有)添加前缀。

换句话说:如果foo是符号链接,并且程序应该遵循符号链接,那么foo/就相当于链接的目标,可能是一个目录。因此,如果foo是目录的符号链接,foo/则是引用该目录的有效方法。但如果foo是常规文件或其他非目录的符号,则foo/不是引用该文件的有效方法。

功能如openENOTDIR如果给定的路径名​​带有尾部斜杠且是现有的非目录,则返回错误。

[ ENOTDIR]
(…)O_CREAT且未O_EXCL指定,路径参数至少包含一个非 <slash> 字符并以一个或多个尾随 <slash> 字符结尾,最后一个路径名组件命名一个既不是目录也不是目录的现有文件目录的符号链接 (...)

斜线的影响*/隐含地描述在中关于模式匹配的部分sh。模式中的the 没有特殊规则/(除了它不能出现在括号表达式中的规则之外,这与这里无关)。因此,/模式中的a必须/与路径名中的 a 匹配。例如,模式*/匹配foo/但不匹配foo。因此,*/匹配目录和目录的符号链接,但不匹配常规文件、常规文件的符号链接、损坏的符号链接、命名管道等。

答案2

有几个提示a*/应该只匹配目录是 bash 手册(强调我的):

  1. *
    匹配任何字符串,包括空字符串。当启用 globstar shell 选项,并且在路径名扩展上下文中使用 * 时,用作单个模式的两个相邻 * 将匹配所有文件以及零个或多个目录和子目录。 如果后面跟一个 /, 两个相邻的 *将仅匹配目录和子目录

    很明显,a**/将仅匹配目录和子目录,这似乎暗示 a*/也应该匹配。

  2. globstar
    如果设置,路径名扩展上下文中使用的模式 ** 将匹配所有文件以及零个或多个目录和子目录。 如果模式后跟 /,则仅目录和子目录匹配

    重复上面的提示。

在 zsh 手册中:

  1. -g globstring
    使用文件名通配符扩展 globstring;应该引用它以防止它立即扩展。结果文件名被视为可能的补全。使用`*(/)' `*/'不是目录

    其中明确指出 a*/应该表示目录在其他地方

但唯一真正的确认来自 ksh 手册:

*
匹配任何字符串,包括空字符串。当用于文件名扩展时,如果启用了 globstar 选项,则两个相邻的 * 本身将匹配所有文件以及零个或多个目录和子目录。如果 后跟 / 则只有目录和子目录会匹配

这明确说明了单身人士*应该做什么。

鉴于 POSIX 主要基于 ksh 的工作方式,并且 bash 和 zsh 尝试模拟 ksh 的工作方式,因此可以合理地预期所有三本手册都会重复相同的功能。

答案3

您可以在中找到一些解释bash 手册,模式匹配

3.5.8.1 模式匹配

除了下面描述的特殊模式字符之外,出现在模式中的任何字符都与自身匹配。 NUL 字符不能出现在模式中。反斜杠转义后面的字符;匹配时转义的反斜杠将被丢弃。如果要按字面匹配特殊模式字符,则必须用引号引起来。

特殊模式字符的含义如下:

*

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

并且在Linux 文档项目您可以找到以下解释echo *

重击执行文件名扩展关于不带引号的命令行参数。 echo 命令演示了这一点。

bash$ echo * a.1 b.1 c.1 t2.sh test1.txt`

bash$ echo t* t2.sh test1.txt

bash$ echo t?.sh t2.sh```

答案4

的扩展*/对于 shell 来说没有什么特别的意义。与展开*.txt将列出所有完全相同现有路径名结束于.txt.

为了任何shell 中, a*/将扩展到所有以/.

那么唯一的问题是理解什么时候 apathname可以以 a 结尾/

仅当最后一个文件名存在并且是目录时才可能。

显式确认(来自 man ksh):

*
...如果后跟 / 则仅匹配目录和子目录。

相关内容