I found that this would raise the "argument too long" error:
ls *.*
And this would not raise it:
for file in *.*
do
echo $file
done
Why?
I found that this would raise the "argument too long" error:
ls *.*
And this would not raise it:
for file in *.*
do
echo $file
done
Why?
The “argument too long” error is E2BIG
, raised by the execve
system call if the total size of the arguments (plus the environment, on some systems) is too large. The execve
call is the one that starts external processes, specifically loading a different executable file (there's a different call, fork
, for running a separate process whose code is still from the same executable file). The for
loop is an internal shell construct, so it doesn't involve calling execve
. The command ls *.*
raises the error not when the glob is expanded but when ls
is called.
execve
fails with the error E2BIG
when the total size of the arguments to the command is larger than the ARG_MAX
limit. You can see the value of this limit on your system with the command getconf ARG_MAX
. (It's possible that you can go over this limit if you have enough memory; keeping under ARG_MAX
guarantees that execve
will work as long as no unrelated error occurs.)
execve
limit is enforced by the kernel, it puts limits because the arguments need to be copied via kernel memory at one point and user processes can't be allowed to request an arbitrary amount of shell memory. Inside the shell, there's no reason to have any limit, anything that fits in virtual memory is fine.
– Gilles 'SO- stop being evil'
Sep 15 '11 at 07:21
I suppose that in the first example ls
is executed from bash
through a fork
/exec
pair system call, in the second one, all the working is internal to bash
.
The exec
call has limits, the internal working of bash
instead has not (or better, has different limits that have nothing to do with exec
, perhaps the amount of available memory).
exec
in /usr/include/linux/limits.h
usually, defined as ARG_MAX
.
– jw013
Sep 14 '11 at 12:47
Because in the case of ls
it is an argument, and the number of arguments is limited.
In case of the for
cycle, it is just a list of items. There are no limits (as far as I'm aware) for that.
for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
– Peter.O
Sep 14 '11 at 12:48
/bin/bash
vs./bin/sh
(which is perhaps a link to dash)? – maxschlepzig Sep 14 '11 at 08:11