"argument list too long" 限制是否适用于 shell 内置函数?

Does "argument list too long" restriction apply to shell builtins?

我在 Stack Overflow 上浏览了很多 posts 以及一些关于 argument list too long 主题的相关社区,但我似乎不清楚长度限制是否适用于 shell 是否内置。

假设我想通过标准输入将一个很长的字符串传递给一个命令:

string="a very long list of words ..."

我可以说:

# not using double quotes around $string is deliberate
printf '%s\n' $string | cmd ...

cmd <<< $string

甚至通过管道将其传送到 xargs:

printf '%s\n' $string | xargs cmd ...

有人可以澄清一下吗?

I don't seem to figure if the length restriction applies to shell builtins or not.

可能不是,但您应该检查特定版本 bash 的源代码(因为它是免费软件)。但是,显然存在一些 - 希望更大 - 限制(特别是因为在 bash 内完成的某些 malloc 可能会失败),但随后您会收到另一个错误消息或行为。

AFAIK,参数列表太长错误由 execve(2) 给出 E2BIG 失败,bash 的内置函数不 fork 然后 execve(就像调用外部程序的命令一样)。

实际上,E2BIG 可能会出现几十万字节(确切的限制取决于内核和系统),但我猜内置函数可以用于几十兆字节(在今天的桌面上) .但是 YMMV(因为你可以使用 ulimit 让你的 shell 做一些 setrlimit(2)...)。我不建议通过 shell 内置函数处理千兆字节的数据。

顺便说一句,xargs(1) 可能会有所帮助,您甚至可以通过重新编译内核(以及通过一些其他方式,在最近的内核中)来提高限制(对于 E2BIG)。几年前,这是我重新编译内核的强大动力。

在 bash 中,导致错误 argument list too long 的 OS 对命令行长度的强制限制不适用于 shell 内置函数。

此错误在 execve() 系统调用 returns 错误代码 E2BIG 时触发。调用内置时没有execve()调用,所以不会发生错误。

因此,您提出的两个操作都是安全的:cmd <<< "$string"$string 写入临时文件,不需要将其作为 argv 元素(或环境变量,这存储在同一个保留池space); printf '%s\n' "$cmd" 发生在 shell 内部,除非 shell 的配置已被修改,如 enable -n printf,以使用外部 printf 实现。