xargs is a unix command that allows you to do some stuff to a list of stuff. The man page is pretty indecipherable, so I shall be doing my explanation with mainly examples.

Example 1:

find . -name frog* | xargs -i ls -l {}

In this example, we use xargs with the '-i' switch, which basically means "take a line from the input, and shove it into the place on the command line where {} is"

The find command itself searches for files that start with 'frog' recursively from the current directory up. Find will generate output like this :

./your/directory/frogfiles/frog1.txt
./your/directory/frogfiles/frogfile.txt
./your/directory/frogfiles/frogfun.txt
./your/directory/frogfiles/frogurt_the_frog_yogurt.txt

Which is conveniently a list of file locations that most programs can process. Each line of this list is sent to xargs, and xargs in turn executes the command(s) given to it as an argument with the appropriate line replacing the curly braces on the command line. If you were to do :

find . -name frog* > frogfiles.txt
cat frogfiles.txt | xargs -i ls -l {}

The same exact thing would be accomplished, only with more steps. For reference, the following is what you would have to type in order to get this done without xargs :

ls -l ./your/directory/frogfiles/frog1.txt
ls -l ./your/directory/frogfiles/frogfile.txt
ls -l ./your/directory/frogfiles/frogfun.txt
ls -l ./your/directory/frogfiles/frogurt_the_frog_yogurt.txt

Which isn't all too bad, but it becomes bad really quick if you have 7000 files beginning with frog in 40 different directories. xargs suddenly becomes your best friend, then.

Example 2:

find / -name core | xargs -i rm -rf {}

Here, we look for core files on the whole system, and if we see one, we kill it off. This might traverse your proc filesystem and totally fuck you over by trying to delete files that aren't actually files, so you might want to restrict this to a directory like /home or /root if you want to watch out for that sort of thing.

Example 3:

You have a program like 'mtv' (which is an mpeg viewer for unix) that doesn't process wildcards, but you'd like to run a bunch of mpegs in a row without typing in the commands.

ls --color=none -1 *.mpg | xargs -i mtv {}

Notice the arguments with which 'ls' is run. This is usually necessary if you have color-ls turned on by default (most people do).

The '-1' argument to ls tells it to list files one row at a time. You want ls to do this rather than trying to fit as many filenames as possible on a line. 'mtv' can't take multiple files as an argument, if it could, we wouldn't be using xargs -- teehee.

Again, we pipe the first command, which finds the filenames of the files that we're interested in to xargs. Xargs reads to output of the first command line by line, and sticks each line into the place where you have placed {} on the command line.

fun, eh?

Note concerning previous writeup: Unfortunately, if your xargs doesn't have the -i option, you may need to use the -I option. It works slightly differently.

The following is a concise explanation of the most popular usage of xargs. To use it, you will need to have at least watched a person use a unix shell, and it will help to know how to use the for loop and to pipe in bash. Even if you don't, if you've done any amount of programming in the past, you should be able to follow along (though, I am surprised you're reading about xargs at all in such a case.) And without further ado...

~/foo$ ls
Makefile README   TODO
~/foo$ for FILENAME in `ls -1`
> do echo "It's the Filename $FILENAME, that's nice ain't it?"
> done
It's the Filename Makefile, that's nice ain't it?
It's the Filename README, that's nice ain't it?
It's the Filename TODO, that's nice ain't it?
~/foo$ ls -1 | xargs -I FILENAME echo "It's the Filename FILENAME, that's nice ain't it?"
It's the Filename Makefile, that's nice ain't it?
It's the Filename README, that's nice ain't it?
It's the Filename TODO, that's nice ain't it?

I used quotation marks so the shell wouldn't eat my apostrophies, but more importantly to demonstrate that xargs will, like bash, search among and within all arguments for the variable name (which were $FILENAME and FILENAME for my bash and xargs examples, repsectively) provided after the -I option. Also note that the variable name in xargs is, as with bash, case sensitive.

So why should you use xargs instead of bash to accomplish a task like this? Behold the entertaining world of bash character escaping...

~/foo$ touch "Filename Containing Spaces"
~/foo$ ls
Filename Containing Spaces Makefile                   README                     TODO
~/foo$ for FILENAME in `ls -1`
> do echo "It's the Filename $FILENAME, that's nice ain't it?"
> done
It's the Filename Filename, that's nice ain't it?
It's the Filename Containing, that's nice ain't it?
It's the Filename Spaces, that's nice ain't it?
It's the Filename Makefile, that's nice ain't it?
It's the Filename README, that's nice ain't it?
It's the Filename TODO, that's nice ain't it?
~/foo$

As you can see, bash will not handle this the way you wanted. xargs is also capable of using many separator characters such as null characters, and eof characters. Additionally, xargs is less work to use a lot of the time, because you can forego the lengthy for loop and messy. Use xargs!

~/foo$ ls -1 | xargs -I FILENAME echo "It's the Filename FILENAME, that's nice ain't it?"
It's the Filename Filename Containing Spaces, that's nice ain't it?
It's the Filename Makefile, that's nice ain't it?
It's the Filename README, that's nice ain't it?
It's the Filename TODO, that's nice ain't it?
~/foo$

Log in or register to write something here or to contact authors.