Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Mildly interesting zargs trick: call an anonymous function



Leonardo Barbosa's question got me thinking:  What if the number of files
is so large that "rm" chokes with "argument list too long" or the like?

Then you want to use zargs to split the list into managable chunks:

    zargs -- **/*.tex(.:s/.tex/.aux) -- rm

However, there's only so much stuff you can pack into the recursive glob
before it begins to get unweildy.  So if it were more complicated than
this example, you could define a function to do the heavy work.

    rm_aux() { rm ${*:s/.tex/.aux} }
    zargs -- **/*.tex(.) -- rm_aux

That lets us use the array tricks without creating a global array, but
leaves the function rm_aux hanging around.  Wouldn't it be nice to use
one of those "anonymous" functions supported by recent zsh?

    ## DO NOT DO THIS:
    zargs -- **/*.tex(.) -- (){ rm ${*:s/.tex/.aux} }

Oops, we've just defined zargs, --, and all our .tex file names to be
functions that execute "rm".  That's no good, we have to quote the
anonymous function.

    ## THIS SPEWS "command not found":
    zargs -- **/*.tex(.) -- '(){ rm ${*:s/.tex/.aux} }'

    ## BUT DO NOT DO THIS EITHER:
    zargs -- **/*.tex(.) -- eval '(){ rm ${*:s/.tex/.aux} }'

That seems fine, but if any of the .tex files has special characters
or whitespace in its path name, that "eval" may do horrible things.
Fortunately, there's a simple glob qualifier that will quote all of
that stuff for us.

    ## I AM PRETTY SURE THIS ONE IS OK, BUT NO WARRANTY:
    zargs -- **/*.tex(.:q) -- eval '(){ rm ${*:s/.tex/.aux} }'

There are of course other ways to slice up this particular example.

    zargs -- **/*.tex(.:rq) -- eval '(){ rm ${^*}.aux }'

Other variations left as exercises for the reader.



Messages sorted by: Reverse Date, Date, Thread, Author