Thursday, November 22, 2012

7 examples of find command with xargs in Linux

 find command becomes very powerful when used with xargs. xargs is a beautiful command which actually builds a command and executes it. Though xargs command can be used standalone to work on standard input or on a file, it becomes all the more powerful when used with the find command. The man page definition of xargs is :"build and execute command lines from standard input"

Let us see some examples of find command with xargs to understand more:

1. Copy a file xyz.c to all the .c files present in the C directory:
$ find ./C -name "*.c" | xargs -n1  cp xyz.c
   find command finds all the files with .c extension from the C directory. xargs command builds the cp commands to copy the file xyz.c onto every file returned by the find command. By default, xargs removes the new line characters from the standard input. Hence, assuming the find command returned 2 files(f1.c and f2.c), the cp command built by the xargs will look like this:
cp xyz.c f1.c f2.c
i.e, all the arguments are formed in the same line. And hence, the usage of the option "-n". -n tells the number of arguments to be used in building a command which in this case is 1. Hence, now the cp command built by xargs looks like:
cp xyz.c f1.c
cp xyz.c f2.c
  which exactly is what we want. The xargs not only builds the command, it also executes it. As a result, the xyz.c gets copied to all the .c files returned by the find. To get better clarity of the above command, just put an echo before the cp and check out the result:
$ find ./C -name "*.c" | xargs -n1  echo cp xyz.c
    This will just show the copy commands built, will not execute it, since actually the command being built here is the echo command.

2. Copy a file xyz.c to all the .c files present in the C directory wherein the .c files can also contain spaces or newlines in the filename:
$ find . -name "*c" -print0 | xargs -0 -n1 cp xyz.c
   Interesting one!! The print0 option of the find command prints the file names with the null character as termination character, instead of the default newline character. This is very helpful in identifying the filenames in case of filenames containing spaces or tabs or newline characters. In fact, the print0 of find is mainly present so that the subsequent programs processing the find command result can work better. Similarly, by using the -0 option with xargs, it starts looking for the null character for reading filenames from the stdin instead of the newline character.
   For this reason, it is always advised to use -print0 in the find instead of the default print.

3. Copy a file xyz.c to all the directories whose name begins with temp:
$ find . -type d -name "temp*" | xargs -n1 cp xyz.c
   This is self explanatory.

4. Move all the .c files to the "temp" directory :
$ find . -name "*.c" -print0 | xargs -0 -n1  -I '{}' mv '{}' temp
  The usage of  -I. The option -I is followed by a string which in this case is '{}'. This -I tells to  replace the occurence of the string in the argument list with the names read from the standard input.
   If the .c files present are f1.c and f2.c, the above xargs command will translate to:
mv f1.c temp
mv f2.c temp
5. To search for a pattern in all the .c files:
$ find . -name "*.c" | xargs grep pattern
  No usage of -n in this. Without -n in the xargs, the grep command built will be:
grep patternn file1 file2 filen ....
   which is perfectly valid for grep to contain more than one file.  Also, this improves performance since the grep command is trigerred only once for the entire file list.

6. To delete all the .c files present using xargs:
$ find . -name "*.c" | xargs rm -f
  Though this is option using xargs, -delete option of find command itself can be used for the same.

7. To list all the .c files in a 3 column format:
$ find . -name "*.c" | xargs -n3 echo
   -n 3 tells to read 3 arguments at a time. echo simply echoes the files in a 3 column list. Also, echo is an optional one here since the default command built by xargs is echo.
     This should also do the same:
$ find . -name "*.c" | xargs -n3

No comments:

Post a Comment