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

non*_*ity 10 shell bash zsh slash wildcards

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

好像只表示所有“目录”,而*表示“所有文件和目录”,但不知为何,很多用户似乎不知道,书籍也没有提到。

是否有明确的来源谈论什么*/意味着及其变化?

Gil*_*il' 19

POSIX规范是基于Unix工具应该如何表现的权威参考。将在路径名解析部分解释了文件名末尾斜杠的含义。

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

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

上面的句子是不完整的:foo/实际上是引用指向目录的符号链接的有效方法。这在下面指定:

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

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

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

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

如果给定的路径名​​带有作为现有非目录的尾随斜杠,则诸如此类的函数将open返回错误ENOTDIR

[ ENOTDIR]
(...)O_CREATO_EXCL未指定,路径参数包含至少一个非<斜线>字符和与一端或多个尾随<斜线>字符,并且最后一个路径名部分表示一个现有的文件,它是既不是目录也不指向目录的符号链接 (...)

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

  • @nonopolarity 这个观点是胡言乱语。在 POSIX 中,文件名(包括目录名)不得包含斜杠。 (6认同)
  • 我会说 `foo` 是正式名称,但 `foo/` 是一个有效的 _path_,它指的是 `foo`。将此与其他模式进行比较:例如,`*/bar` 匹配位于任何目录中的 `bar` 文件 - 它不是在寻找字面上名为“&lt;anything&gt;/bar”的文件,而是在寻找路径 `&lt;anything &gt; / bar` 用于定位有效文件。glob 匹配与 _path_ 不匹配,而不是 _name_。 (4认同)

sch*_*ity 1

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

\n\n
\n

3.5.8.1 模式匹配

\n\n

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

\n\n

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

\n\n

*

\n\n

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

\n
\n\n

Linux 文档项目中,您可以找到有关以下内容的解释echo *

\n\n
\n

Bash对不带引号的命令行参数执行文件名扩展。\n echo 命令演示了这一点。

\n\n
bash$ echo * a.1 b.1 c.1 t2.sh test1.txt`\n\nbash$ echo t* t2.sh test1.txt\n\nbash$ echo t?.sh t2.sh```\n
Run Code Online (Sandbox Code Playgroud)\n
\n