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.)
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).
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.