CP:复制实用程序的最大源文件数参数

Mik*_*ike 12 cp arguments

考虑到 /src/ 下有无数个文件

cp /src/* /dst/
Run Code Online (Sandbox Code Playgroud)

cp将成功处理多少个文件?

Sté*_*las 21

这在很大程度上取决于系统和版本、参数的数量和大小以及环境变量名称的数量和大小。

传统上,在 Unix 上,限制(如 所报告的getconf ARG_MAX)或多或少取决于:

  • 参数字符串的长度(包括终止'\0'
  • 指向这些字符串的指针数组的长度,因此在 64 位系统上每个参数通常为 8 个字节
  • 环境字符串的长度(包括终止的'\0'),按照约定,环境字符串类似于var=value.
  • 指向这些字符串的指针数组的长度,因此在 64 位系统上每个参数通常为 8 个字节

请记住,这cp也算作一个论点(是第一个论点)。

在 Linux 上,这取决于版本。那里的行为最近发生了变化,不再是固定空间。

在 Linux 3.11 上检查,getconf ARG_MAX现在报告堆栈大小限制的四分之一,如果小于 512kiB,则为 128kiB)。

zsh语法如下):

$ limit stacksize
stacksize       8MB
$ getconf ARG_MAX
2097152
$ limit stacksize 4M
$ getconf ARG_MAX
1048576
Run Code Online (Sandbox Code Playgroud)

该限制是参数和环境字符串的累积大小以及一些开销(我怀疑是由于页面边界的对齐考虑)。不考虑指针的大小。

寻找极限,我得到:

$ /bin/true {1..164686}
$ /bin/true {1..164687}
zsh: argument list too long: /bin/true
$ x= /bin/true {1..164686}
$ x=1 /bin/true {1..164686}
zsh: argument list too long: /bin/true
Run Code Online (Sandbox Code Playgroud)

在这种情况下,中断前的最大累积大小为:

$ (env _=/bin/true x=;print -l /bin/true {1..164686}) | wc -c
1044462
Run Code Online (Sandbox Code Playgroud)

现在,这并不意味着您可以传递 100 万个空参数。在 64 位系统上,100 万个空参数构成一个 8MB 的指针列表,这将超过我 4MiB 的堆栈大小。

$ IFS=:; /bin/true ${=${(l[1000000][:])}}
zsh: killed     /bin/true ${=${(l[1000000][:])}}
Run Code Online (Sandbox Code Playgroud)

(你会注意到这不是 E2BIG 错误。我不确定进程在哪一点被杀死,但如果它在execve系统调用中或之后)。

另请注意(仍在 Linux 3.11 上)单个参数或环境字符串的最大大小为 128kiB,与堆栈大小无关。

$ /bin/true ${(l[131071][a])} # 131072 OK
$ /bin/true ${(l[131072][a])} # 131073 not
zsh: argument list too long: /bin/true
$ /bin/true ${(l[131071][a])} ${(l[131071][a])} # 2x 131072 OK
Run Code Online (Sandbox Code Playgroud)


ter*_*don 15

这将取决于可以在系统之间变化的 ARG_MAX 的值。要找出系统运行的值(以我的结果为例):

$ getconf ARG_MAX
2097152
Run Code Online (Sandbox Code Playgroud)

这与cp您的 shell无关,这是内核强加的限制,exec()如果( ) 命令的参数长于ARG_MAX. 因此,如果您提供的参数列表的长度cp大于 ARG_MAX,则该cp命令根本不会运行。

那么要回答您的主要问题,cp将不处理任何文件,因为它永远不会使用这么多参数执行。我还应该提到,这不取决于参数的数量,而是取决于它们的长度。可以想象,对于很少但很长的文件名,您可能会遇到同样的问题。


解决这些错误的方法是在循环中运行您的命令:

for file in /src/*; do cp "$file" /dst/; done
Run Code Online (Sandbox Code Playgroud)