Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!ucbvax!agate!pasteur!buddy.Berkeley.EDU!deboor From: deboor@buddy.Berkeley.EDU (Adam R de Boor) Newsgroups: comp.unix.wizards Subject: Re: Look! An xargs!! (Re: recursive grep) Message-ID: <16836@pasteur.Berkeley.EDU> Date: 5 Sep 89 04:41:46 GMT References: <666@lakart.UUCP> <1641@cbnewsl.ATT.COM> <7774@cbmvax.UUCP> <16816@pasteur.Berkeley.EDU> <1126@virtech.UUCP> Sender: news@pasteur.Berkeley.EDU Reply-To: deboor@buddy.Berkeley.EDU.UUCP (Adam R de Boor) Organization: University of California, Berkeley Lines: 56 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