The numbers that matter are the total length of (all) the arguments, and the command buffer size xargs decides to use.
The first depends on the fixed command line to the command you run, and the arguments xargs gives each invocation. perl -E 'say "ok:", scalar @ARGV'
is 32 bytes, counting the NUL bytes that terminate the strings (i.e. perl<NUL>-E<NUL>say "ok:", scalar @ARGV<NUL>
. And in the second example, all the arguments are two bytes each, 1<NUL>
. So 32 + 65520 * 2 bytes, or 131072 B = 128 * 1024 B = 128 kB.
Obviously in the first example, the lengths of arguments vary, giving varying counts, but the logic should be the same. E.g. 21840 args for the second to fourth runs matches 5-digit arguments (6 bytes each): 21840 * 6 + 32 = 131072.
The size of the command buffer may depend on the implementation, but GNU xargs can show it with xargs --show-limits
, and on my Linux, I get:
$ echo | xargs --show-limits
Your environment variables take up 2305 bytes
POSIX upper limit on argument length (this system): 2092799
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2090494
Size of command buffer we are actually using: 131072
Maximum parallelism (--max-procs must be no greater): 2147483647
Looking at the second to last line, that's exactly the same number.
You can change the size of the buffer it uses with -s
, e.g. with just 10 kB buffer:
$ perl -E' say "1 " x 90000' | xargs -s 10240 perl -E 'say "ok:", scalar @ARGV'
ok:5104
ok:5104
ok:5104
...
And of course there's also -n
to limit the number of individual arguments:
$ echo {1..200000} | xargs -n 10000 perl -E 'say "ok:", scalar @ARGV'
ok:10000
ok:10000
ok:10000
...
--show-limits
mentions environment variables because they use the same space as command line arguments, and if you raise the buffer size enough, close to the system maximum, their size starts to matter too.
I'm not sure if the system also counts the sizes of the pointers to the argument strings against the limit, but at least xargs doesn't seem to care about that.