Look! An xargs!! (Re: recursive grep)

Adam R de Boor deboor at buddy.Berkeley.EDU
Tue Sep 5 14:41:46 AEST 1989


ooooooooo. meanie! I guess I've been pampered by using the Sun sh. Gotten
burned a few times from having {} be in a subshell, but never a while loop.
This one will do more work, but should be correct. Of course, I don't have
a limited sh, so who knows? I've tested this on my system and it does
The Right Thing... 

I *do* hope you'll have the good grace to not mention how early versions of
the shell didn't accept comments? (lots o' grins here).

#!/bin/sh -
#
# Remove all possible temp files we might create on exit or signal...
#
tmpbase=/tmp/xargs$$
trap "rm -f ${tmpbase}*; exit 0" 0 1 2 3 15

#
# Assume command has no spaces, but quote the rest of the args to make sure
# If your system doesn't have echo -n, remove the -n and add a \c at the
# end of each string.
#
cmd=`echo -n "$1 "; shift; for i in "$@"; do echo -n "'$i' "; done`
#
# Copy all the args to a file for easier processing without worry about
# overflowing shell variables.
#
cat - > $tmpbase
#
# If file small enough (say 4000 bytes), just execute the command directly.
# Use "set" to put the length and filename produced by "wc" into $1 and $2
# since we're done with our args anyway.
#
# Note we need to use tr to map from newline to space in all the files,
# else the shell will execute the command on the first file, then try
# and execute all the remaining files, since it keeps the newlines from the cat
#
# "eval" is necessary to cause $cmd to be broken into component words. The
# ''s we put around $2-n will keep spaces in them from getting in the way,
# as well as avoiding any wildcard expansion that might otherwise happen.
#
set - `wc -c $tmpbase`
if [ $1 -le 4000 ]; then
    eval "$cmd `cat $tmpbase | tr '\012' ' '`"
else
    #
    # Tough luck. Since we're working on filenames, we'll be really
    # conservative and break the list into 50-file groups. That gives
    # 80-chars per name with our conservative limit of 4000 (though
    # all the MAXARGS system constants I've seen are above 10000)
    #
    split -50 $tmpbase ${tmpbase}s
    for i in ${tmpbase}s*; do
	eval "$cmd `cat $i | tr '\012' ' '`"
    done
fi



More information about the Comp.unix.wizards mailing list