[CentOS] Re: ls and rm: "argument list too long"

Sat Oct 18 10:00:23 UTC 2008
William L. Maltby <CentOS4Bill at triad.rr.com>

On Fri, 2008-10-17 at 23:52 -0500, Les Mikesell wrote:
> Robert Nichols wrote:
> > 
> >> These shouldn't make any difference.  The limit is on the size of the 
> >> expanded shell command line.
> > 
> > Really?
> > 
> > $ M=0; N=0; for W in `find /usr -xdev 2>/dev/null`; do M=$(($M+1)); 
> > N=$(($N+${#W}+1)); done; echo $M $N
> > 156304 7677373
> > 
> > vs.
> > 
> > $ /bin/echo `find /usr -xdev 2>/dev/null`
> > bash: /bin/echo: Argument list too long
> > 
> > For the first case, the shell never tries to pass the list as command 
> > arguments.
> > It builds the list internally, limited only by memory size, and 
> > processes the
> > words one by one.
> 
> Is that peculiar to bash?  I thought the `command` construct was 
> expanded by shells into the command line before being evaluated.

IIRC, none of the above make a "command line". Everything but the 

    `find /usr -xdev 2>/dev/null`

is a bash "internal command". IIRC, what should happen here is a new
instance of bash is spawned as part of a pipeline that sends the output
of the find (which is "exec'd" by that new instance of bash, the child)
into the parent. The parent reads the input from the pipe and can do
whatever it wants, in this case build an array. It then uses the array
as data to the loop.

The "command line" is never constructed with the long list. It is only
passed to the child (the new instance of bash that is part of the
pipeline). That instance receives an argument count and an array of
pointers to the arguments. In "C" parlance it looks something like this.

    main(argc, *argv[])  /* could be **argv instead */
    {
         /* stuff to do */
            .
            .
            .
    }

The "*argv[]" pointers point to the parts of the "command line",

    find /usr -xdev

The child execs find, passing the "/usr" and "-xdev" as arguments to
find (which has a similar "main" construct), another "command line". The
I/O redirection was already done by the parent, so the child need not
even know that "stdout" is a pipe.

The longest command line in this case is "find /usr -xdev', 15
characters. Find "sees" only 10 characters.

I hope I've remembered correctly, that this is not FUD, and that it
helps someone.
   
> <snip>

-- 
Bill