Unix Power Tools
Handle Too-Long Command Lines with xargs
by Jerry Peek
02/03/2000
xargs is one of those UNIX utilities that seems pretty
useless when you first hear about it -- but turns into one of the
handiest tools you can have.
xargs reads a group of arguments from its standard
input, then runs a UNIX command with that group of arguments. It
keeps reading arguments and running the command until it runs out of
arguments. The shell's backquotes do the same kind of thing, but they
give all the arguments to the command at once. This can give you a
Too many arguments error.
Here are a couple of examples:
If you want to print most of the files in a large directory, put the output of
lsinto a file. Edit the file to leave just the filenames you want printed. Give the file toxargs' standard input:% ls > allfiles.tmp % vi allfiles.tmp % xargs lpr < allfiles.tmpWhat did that do? With lines like these in
allfiles.tmp:% cat allfiles.tmp afile application ... yoyotest zapmexargsran one or morelprcommands, each with a group of arguments, until it had read every word in the file:lpr afile application ... ... lpr ... yoyotest zapmeThe standard output of
xargsis the standard output of the commands it runs. So, if you'd createdallfiles.tmpabove but you wanted to format the files withprfirst, you could type:% xargs pr < allfiles.tmp | lprThen
xargswould run all of theseprcommands. The shell would pipe their standard outputs to a singlelprcommand. Actually, the shell is piping the standard output ofxargs. As I said above,xargssends the standard output of commands it runs to its own standard output:pr afile application ... ... pr ... yoyotest zapmeIn this next example,
findgets a list of all files in the directory tree. Next, we usexargsto read those filenames and rungrep - lto find which files contain the word "WARNING". Next, we pipe that to a setup withprandlpr, like the one in the previous example:% find . -type f -print | xargs grep -l WARNING | xargs pr | lpr"Huh?" you might say. Just take that step by step. The output of
findis a list of filenames, like ./afile ./bfile ... ./adir/zfile and so on. The firstxargsgives those filenames to one or moregrep - lcommands:grep -l WARNING ./afile ./bfile ... ... grep -l WARNING ./adir/zfile ...The standard output of all those
greps is a (shortened) list of filenames that match. That's piped to anotherxargs- it runsprcommands with the filenames thatgrepfound.UNIX is weird and wonderful!
Sometimes you don't want
xargsto run its command with as many arguments as it can fit on the command line. The- noption sets the maximum number of argumentsxargswill give to each command. Another handy option,- p, prompts you before running each command.Here's a directory full of files with errors (whose names end with
.bad) and corrected versions (named.fixed). I uselsto give the list of files toxargs; it reads two filenames at once, then asks whether I want to rundiff - cto compare those two files. It keeps prompting me and runningdiff - cuntil it runs out of file pairs:% ls chap1.bad chap1.fixed chap2.bad chap2.fixed ... chap9.bad chap9.fixed % ls | xargs -p -n2 diff -c diff -c chap1.bad chap1.fixed ?...y ...... diff -c chap2.bad chap2.fixed ?...n diff -c chap3.bad chap3.fixed ?...y ...... ...
As tomorrow's article explains, xargs can have trouble if an argument has white space
inside a word.
Luckily, the GNU xargs solves the problem.