所以按照POSIX规范我们有以下定义*
:
扩展到位置参数,从 1 开始,最初为设置的每个位置参数生成一个字段。当扩展发生在将执行字段拆分的上下文中时,任何空字段都可能被丢弃,并且每个非空字段应进一步拆分,如字段拆分中所述。当扩展发生在不执行字段拆分的上下文中时,如果 IFS 包含至少一个字符,则初始字段应连接以形成单个字段,每个参数的值由 IFS 变量的第一个字符分隔,或者如果未设置 IFS,则用 a 分隔;如果 IFS 设置为空字符串,则不使用分隔符。
对于绝大多数人来说,我们都知道一个著名的ARG_MAX
限制:
$ getconf ARG_MAX
2621440
这可能会导致:
$ cat * | sort -u > /tmp/bla.txt
-bash: /bin/cat: Argument list too long
值得庆幸的是,背后的好人bash
([包括所有类似 POSIX 的其他人])为我们提供了printf
内置功能,因此我们可以简单地:
printf '%s\0' * | sort -u --files0-from=- > /tmp/bla.txt
一切对用户来说都是透明的。
有人可以告诉我为什么ARG_MAX
使用built-in
命令绕过限制是如此简单,以及为什么提供一个一致的 POSIX shell 解释器来优雅地处理*
独立可执行文件的特殊参数是如此困难:
$ cat *
那会破坏什么东西吗?我并不是要求bash
人们提供cat
内置命令,我只对操作顺序感兴趣,以及为什么*
根据命令是内置命令还是独立可执行文件以不同的行为进行扩展。
答案1
限制不在于 shell,而在于exec()
函数系列。
POSIX 标准与此相关的说法:
新进程的组合参数和环境列表可用的字节数为
{ARG_MAX}
。空终止符、指针和/或任何对齐字节是否包含在该总数中是由实现定义的。
要运行 shell 中内置的实用程序,shell 不需要调用exec()
,因此它不受此限制的影响。
另请注意,受限制的不仅仅是命令行的长度,还包括命令长度、其参数以及当前环境变量及其值的组合。
还要注意的printf
是不是pdksh
例如(它恰好充当sh
OpenBSD上的)内置实用程序ksh
。依赖它作为内置程序需要考虑正在使用的特定 shell。
答案2
善行难陀的回答解释了为什么ARG_MAX
shell 内置程序没有问题。
就以cat *
不受 影响的方式实现而言ARG_MAX
,这样做是微不足道的:cat
实现所需要做的就是使用glob(3)
来实现它自己的通配符,然后您可以使用cat \*
或运行它cat '*'
,这样 shell 就不会执行自己的通配符。您会发现 Linux 或 Unix 风格的系统上有一些命令可以处理它们自己的通配符,至少在某些情况下是这样;许多具有本机 DOS 版本的命令至少会包含处理通配符的代码,因为那里的 shell 本身不会通配符外部命令的find
参数tar
。zip
考虑到 POSIX shell 的期望,该功能将相当令人惊讶且难以发现!在早期的 Unix 版本中,通配符是使用单独的程序/etc/glob
.