从我有限的研究看来,在 bash 中,全局模式后面的任何多个斜杠都会被截断,如下所示:
echo ////[h]ome////user////Desktop////test////
# outputs ////home/user/Desktop/test/
echo ////home////user////Desktop////tes[t]////
# outputs ////home////user////Desktop////test/
这个结论正确吗?这种行为有定义吗?如果是的话,在哪里?它在不同的 shell 之间共享吗?有什么相关性吗?
我已经阅读了 bash 手册,但找不到任何关于此的内容,尽管我可能错过了一些东西。我知道这些符号之间没有语义差异(除了前导双斜杠的例外),只是不知道这种行为是否是有意的或有目的的。
编辑:所描述的行为发生在 Ubuntu 上的默认 bash 中。Korn shell ( /usr/bin/sh
) 没有截断任何斜杠。
编辑2:只是为了澄清:
- 我不是问Linux如何处理多个斜杠,很明显,除了前导双斜杠异常之外的多个斜杠没有语义意义,可能会被截断。
- 我不是在问这种行为如何影响 shell 管道中的任何内容 - 显然不会,除了如果全局扩展作为参数传递下去,它只是有更多的斜杠。
- 我不是问为什么这种情况会发生在具有 glob 模式的路径上 - 很明显,无论处理 glob 扩展的任何代码也会截断 glob 后面的斜杠。
- 我特别想问这种行为是否是定义的,是否在不同的 shell 之间共享,是有意的还是有目的的。
一些发现:
POSIX明确允许这种行为(删除一些多余的斜杠)。
我认为我们不能从该文本中推断出它是必需的。
我发现的唯一可以做到这一点的其他 shell 是
fish
. 它甚至更进一步:csh
、、、、、、、、、、、、、都不这样做。tcsh
dash
ksh93
mksh
yash
zsh
bosh
rc
es
akanga
我没有测试过任何
glob()
实现。bash 1.13.1(我能够运行的最早版本)已经表现得像这样。
ksh 是 shell,它是 sh 的 POSIX 规范的基础,shell bash 复制了其中的大部分功能,但它的行为却并非如此。
bash 参考手册指出,当匹配文件名时,斜杠字符必须始终与模式中的斜杠显式匹配,但在其他匹配上下文中,它可以通过特殊模式字符进行匹配,如下所述,这并不能证明剥离是合理的冗余
/
s 的。所有这些都表明这可能是一次无意的实施事故。POSIX 不要求它。据我所知,没有其他类似 Bourne/POSIX 的 shell 可以做到这一点。IMO,这是不可取的,因为生成的文件名最终可能与模式不匹配(
case
例如在构造中)。这意味着您不能依赖该行为或脚本中没有该行为
sh
。在脚本中依赖它bash
可能无法适应未来的情况。¹ 尽管还有其他原因导致 glob 可能生成与 中的模式不匹配的路径名
foo[a/b]bar*
。