LINUX - xargs

SIMPLE EXPLANATION OF XARGS
###########################

command1 | xargs command1

Take the output of a command1 and use it as the argument of the next command2, useful when alot of output.

Structure the output of command to your needs.

My steps are first:
1) Select the output you want, which will be the argument of some command (command1)
2) pump the output to xargs which will run the command you are wanting (command2)

To visualize it
----------------
Imagine the output of command1 is

# command1
OUTPUT:
thing1
thing2
thing3
thing4

Then running
# command1 | xargs command2

Is the equivalent of running these:
command2 thing1
command2 thing2
command2 thing3
command2 thing4

This can be very useful if you think about it

EXAMPLE1:
----------

Like wise this returns a bunch of process I want to kill

I know I can delete by PID
First I run "ps aux" To see where the PIDs are at

ps aux | egrep "stupidprogram" 

This will return:
stuff PID stuff stuff <- the header of the output shows me that the PID which I am looking for is in column 2
stuff 1231 stuff stuff
stuff 432 stuff stuff
stuff 5543 stuff stuff

Notice its in the second column so I use awk to select them:

ps aux | egrep "stupidprogram" | awk 'print {print $2}'
This will return:
1231
432
5543

Thats the output that I wanted the PIDS all seperated out for me

Then I use xargs to kill them
ps aux | egrep "stupidprogram" | awk 'print {print $2}' | kill 
ps aux | egrep "stupidprogram" | awk 'print {print $2}' | kill -9

The kill -9 is for super kill :-)


EXAMPLE2:
---------
For example I want to delete all the files named core in my system, without going to each one

A few ways but with xargs:

This command finds all the files(-type f) that are named core (-name "core")
find / -type f -name "core" 

To delete with it:
find / -type f -name "core" -delete 
find / -type f -name "core" -exec rm -rf {} \;
find -type f -name "core" | xargs rm -rf 
find -type f -name "core" -print0 | xargs -0 rm -rf

So find -type f returns abunch of file names and nothing else seperated by new lines.

Whats the difference between "find -type f -name "core" | xargs rm -rf " and  "find -type f -name "core" -print0 | xargs -0 rm -rf"?
Simple never use "find -type f | xargs rm -rf"
Only use "find -type f -print0 | xargs -0 rm -rf"
Why? Because you will never get mistakes and will not delete what you dont want to
The -print0 on find works with the -0 on xargs, they make sure mistakes dont happen when there are spaces or new lines.
IF a file had a space in it the first way would of made a mistake or deleted the wrong stuff
BAD:  find -type f -name "core" | xargs rm -rf 
GOOD: find -type f -name "core" -print0 | xargs -0 rm -rf

The only rare situation is if your file didnt have spaces or any special character. -print0 in find and -0 in xargs protect also from newlines but I never seen a new line in a file name.

EXAMPLE3:
---------

List a bunch of info about the file "core":

First select it:
find / -type f -name "core" 

Then xarg it:
find -type f | xargs ls -lisah
find -type f -print0 | xargs ls -lisah

You see find has a similar option, but it doesnt give the information I wanted:
find -type f -name "core" | xargs ls -lisah
find -type f -name "core" -print0| xargs -0 ls -lisah


EXAMPLE4:
---------

Lets say you are in a folder and want to install alot of files, they are all .deb files.

Now I could run dpkg -i * but actually that wont work, it wont expand like that

Solution:
ls | xargs dpkg -i

Why doesnt dpkg -i * work? Because this doesnt make sense dpkg -i file1 file2 file3 file4, and sometimes programs just dont like *

------------

SIDE NOTE ON exec:
EXERPT FROM: http://www.codecoffee.com/tipsforlinux/articles/21.html
The exec option is probably the most important feature of the find tool. The exec command allows you to execute a particular command on the results of the find command. A simple demonstration of this feature is shown below. Its upto your imagination to make maximum use of this feature. Suppose you wanted to see the details of the files (read, write, execute permission, file size, owner etc..) that have been returned as a search result you could do the following

$ find / - name 'Metallica*' -exec ls -l {\}\ \;

This command would find all the files on your system that begin with the letters 'Metallica' and would then execute the 'ls -l' command on these files. So basically you would be able to see the details of the files that were returned according to your search criteria. 

The words following the -exec option is the command that you want to execute i.e. ls -l in this case.
{\}\ is basically an indicator that the filenames returned by the search should be substituted here.
\; is the terminating string, and is required at the end of the command

MY NOTE: Note that they used {\}\ \; Well in reality you can just get away with {} \;
Dont get confused with the \, its just an escaping character
SelectionFile type iconFile nameDescriptionSizeRevisionTimeUser
Comments