Execute a command with piped arguments coming from another command, a file, etc. The input is treated as a single block of text and split into separate arguments on spaces, tabs, newlines and end-of-file.
# To run a command using the input data as arguments:
<arguments_source> | xargs <command>
# To run multiple chained commands on the input data:
<arguments_source> | xargs sh -c "<command1> && <command2> | <command3>"
# To delete all files with a '.backup' extension ('-print0' uses a null character to split file names, and '-0' uses it as delimiter):
find . -name '*.backup' -print0 | xargs -0 rm -v
# To execute the command once for each input line, replacing any occurrences of the placeholder (here marked as '_') with the input line:
<arguments_source> | xargs -I _ <command> _ <optional_extra_arguments>
# To parallel runs of up to 'max-procs' processes at a time; the default is 1. If 'max-procs' is 0, xargs will run as many processes as possible at a time:
<arguments_source> | xargs -P <max-procs> <command>
# ---
##
# xargs is safer and easy to use
#
# `xargs` functionality can be achived using the backquote feature of shell.
# But, it offers more options. It can deal with blanks or special characters
# in file names easily. It is often used with find, grep and other commands.
##
# The following example will print 1 2 3 4 using xargs (echo command is default)
$ echo 1 2 3 4 | xargs echo
# OR
$ echo 1 2 3 4 | xargs
# You can force xargs to use at most max-args arguments per command line. For
# example, the following will use first two argument per command:
$ echo 1 2 3 4 | xargs -n 2
# Find all .bak files in or below the current directory and delete them.
$ find . -name "*.bak" -type f -print | xargs /bin/rm -f
##
# `{}` as the argument list marker
##
# `{}` is the default argument list marker. You need to use `{}` this with various
# command which take more than two arguments at a time. For example the `mv`
# command needs to know the file name.
# The following will find all .bak files in or below the current directory
# and move them to `~/.old.files` directory:
$ find . -name "*.bak" -print0 | xargs -0 -I {} mv {} ~/old.files
# You can rename `{}` to something else. In the following example `{}` is renamed
# as `file`. This is more readable as compare to previous example:
$ find . -name "*.bak" -print0 | xargs -0 -I file mv file ~/old.files
# [-0] If there are blank spaces or characters (including newlines) many commands
# will not work. This option take cares of file names with blank space.
#
# [-I] Replace occurrences of replace-str in the initial-arguments with names
# read from standard input. Also, unquoted blanks do not terminate input
# items; instead the separator is the newline character.
##
# Dealing file names with blank spaces and newline
##
# The following will work incorrectly if there are any filenames containing
# newlines or spaces (it will find out all .mp3 file located in current directory
# and play them using mplayer):
$ find . -iname "*.mp3" -print | xargs mplayer
# To get rid of this problem use -0 option:
$ find . -iname "*.mp3" -print0 | xargs -0 -I mp3file mplayer mp3file
# To find out all *.c file located in 100s of subdirectories and move them
# to another directory called ~/old.src, use:
$ find /path/to/dir -iname "*.c" -print0 | xargs -0 -I file mv file ~/old.src
##
# Avoiding errors and resource hungry problems with xargs and find combo
##
# To copy all media files to another location called /bakup/iscsi, you can use
# cp as follows:
$ cp -r -v -p /share/media/mp3/ /backup/iscsi/mp3
# However, cp command may fail if an error occurs such as if the number of
# files is too large for the cp command to handle. xargs in combination with
# find can handle such operation nicely. xargs is more resource efficient
# and will not halt with an error:
$ find /share/media/mp3/ -type f -name "*.mp3" -print0 | xargs -0 -r -I file cp -v -p file --target-directory=/bakup/iscsi/mp3
# Please note that all of the above commands are tested with `GNU/xargs`
# version. BSD and UNIX xargs command may not have options such as `-r`.
# -----------------------------------------------------------------------------
# When you are trying to delete too many files using rm, you may get error
# message: `/bin/rm Argument list too long` - Linux. Use `xargs` to avoid
# this problem.
$ find ~ -name '*.log' -print0 | xargs -0 rm -f
# Get a list of all the *.conf file under /etc/. There are different ways
# to get the same result. Following example is only to demonstrate the
# use of xargs. The output of the find command in this example is
# passed to the ls –l one by one using xargs.
$ find /etc -name "*.conf" | xargs ls –l
# If you have a file with list of URLs that you would like to download,
# you can use xargs as shown below.
$ cat url-list.txt | xargs wget –c
# Find out all the jpg images and archive it.
$ find / -name *.jpg -type f -print | xargs tar -cvzf images.tar.gz
# Copy all the images to an external hard-drive.
$ ls *.jpg | xargs -n1 -i cp {} /external-hard-drive/directory
# find all file name ending with .pdf and remove them
find -name *.pdf | xargs rm -rf
# if file name contains spaces you should use this instead
find -name *.pdf | xargs -I{} rm -rf '{}'
# Will show every .pdf like:
# &toto.pdf=
# &titi.pdf=
# -n1 => One file by one file. ( -n2 => 2 files by 2 files )
find -name *.pdf | xargs -I{} -n1 echo '&{}='
##
# Resources
# - [Hack 22. Xargs Command Examples](http://linux.101hacks.com/linux-commands/xargs-command-examples/)
# - [xargs: How To Control and Use Command Line Arguments](http://www.cyberciti.biz/faq/linux-unix-bsd-xargs-construct-argument-lists-utility/)
##