xargs
xargs is a command on Unix and most Unix-like operating systems used to build and execute commands from standard input. It converts input from standard input into arguments to a command.
Some commands such as grep
and awk
can take input either as command-line arguments or from the standard input. However, others such as cp
and echo
can only take input as arguments, which is why xargs is necessary.
Contents
1 Examples
2 Placement of arguments
2.1 -I option
2.2 Shell trick
3 Separator problem
4 Operating on a subset of arguments at a time
5 Encoding problem
6 References
7 External links
7.1 Manual pages
Examples
One use case of the xargs command is to remove a list of files using the rm command. Under the Linux kernel before version 2.6.23, and under many other Unix-like systems, arbitrarily long lists of parameters cannot be passed to a command,[1] so the command may fail with an error message of "Argument list too long" (meaning that the exec system call's limit on the length of a command line was exceeded):
rm /path/*
or
rm $(find /path -type f)
This can be rewritten using the xargs
command to break the list of arguments into sublists small enough to be acceptable:
find /path -type f -print | xargs rm
In the above example, the find
utility feeds the input of xargs
with a long list of file names. xargs
then splits this list into sublists and calls rm
once for every sublist.
xargs can also be used to parallelize operations with the -P maxprocs
argument to specify how many parallel processes should be used to execute the commands over the input argument lists. However, the output streams may not be synchronized. This can be overcome by using an --output file
argument where possible, and then combining the results after processing. The following example queues 24 processes and waits on each to finish before launching another.
find /path -name '*.foo' | xargs -P 24 -I '{}' /cpu/bound/process '{}' -o '{}'.out
xargs often covers the same functionality as the backquote (`) feature of many shells, but is more flexible and often also safer, especially if there are blanks or special characters in the input. It is a good companion for commands that output long lists of files such as find
, locate
and grep
, but only if you use -0
, since xargs
without -0
deals badly with file names containing ', " and space. GNU Parallel is a similar tool that offers better compatibility with find, locate and grep when file names may contain ', ", and space (newline still requires -0
).
Placement of arguments
-I option
The xargs command offers options to insert the listed arguments at some position other than the end of the command line. The -I option to xargs takes a string that will be replaced with the supplied input before the command is executed. A common choice is %.
$ mkdir ~/backups
$ find /path -type f -name '*~' -print0 | xargs -0 -I % cp -a % ~/backups
Shell trick
Another way to achieve a similar effect is to use a shell as the launched command, and deal with the complexity in that shell, for example:
$ mkdir ~/backups
$ find /path -type f -name '*~' -print0 | xargs -0 bash -c 'for filename; do cp -a "$filename" ~/backups; done' bash
The word bash
at the end of the line is interpreted by bash -c
as special parameter $0. If the word bash
weren't present, the name of the first matched file would be assigned to $0
and the file wouldn't be copied to ~/backups
. Any word can be used instead of bash
, but since $0
usually expands to the name of the shell or shell script being executed, bash
is a good choice.
Separator problem
Many Unix utilities are line-oriented. These may work with xargs
as long as the lines do not contain '
, "
, or a space. Some of the Unix utilities can use NUL as record separator (e.g. Perl (requires -0
and instead of
n
), locate
(requires using -0
), find
(requires using -print0
), grep
(requires -z
or -Z
), sort
(requires using -z
)). Using -0
for xargs
deals with the problem, but many Unix utilities cannot use NUL as separator (e.g. head
, tail
, ls
, echo
, sed
, tar -v
, wc
, which
).
But often people forget this and assume xargs
is also line-oriented, which is not the case (per default xargs
separates on newlines and blanks within lines, substrings with blanks must be single- or double-quoted).
The separator problem is illustrated here:
touch important_file
touch 'not important_file'
find . -name not* | tail -1 | xargs rm
mkdir -p '12" records'
find ! -name . -type d | tail -1 | xargs rmdir
Running the above will cause important_file
to be removed but will remove neither the directory called 12" records
, nor the file called not important_file
.
The proper fix is to use the -print0
option, but tail
(and other tools) do not support NUL-terminated strings:
touch important_file
touch 'not important_file'
find . -name not* -print0 | xargs -0 rm
mkdir -p '12" records'
find ! -name . -type d -print0 | xargs -0 rmdir
When using the -print0
option, entries are separated by a null character instead of an end-of-line. This is equivalent to the more verbose command:
find . -name not* | tr \n \0 | xargs -0 rm
or shorter, by switching xargs
to line-oriented mode with the -d
(delimiter) option:
find . -name not* | xargs -d 'n' rm
but in general using the -0
option should be preferred, since newlines in filenames are still a problem.
GNU parallel
is an alternative to xargs
that is designed to have the same options, but be line-oriented. Thus, using GNU Parallel instead, the above would work as expected.[2]
For Unix environments where xargs
does not support the -0
option (e.g. Solaris, AIX), the following can not be used as it does not deal with ' and " (GNU parallel
would work on Solaris, though):
find . -name not* | sed 's/ /\ /g' | xargs rm
For Solaris, do not use these examples to fix file perms as they do not deal correctly with names such as 12" records (GNU parallel
instead of xargs
would work, though):
find . -type d -print | sed -e 's/^/"/' -e 's/$/"/' | xargs chmod 755
find . -type f -print | sed -e 's/^/"/' -e 's/$/"/' | xargs chmod 644
Operating on a subset of arguments at a time
One might be dealing with commands that can only accept one or maybe two arguments at a time. For example, the diff
command operates on two files at a time. The -n
option to xargs
specifies how many arguments at a time to supply to the given command. The command will be invoked repeatedly until all input is exhausted. Note that on the last invocation one might get fewer than the desired number of arguments if there is insufficient input. Use xargs
to break up the input into two arguments per line:
$ echo {0..9} | xargs -n 2
0 1
2 3
4 5
6 7
8 9
In addition to running based on a specified number of arguments at a time, one can also invoke a command for each line of input with the -L 1
option. One can use an arbitrary number of lines at a time, but one is most common. Here is how one might diff
every git commit against its parent.[3]
$ git log --format="%H %P" | xargs -L 1 git diff
Encoding problem
The argument separator processing of xargs
is not the only problem with using the xargs
program in its default mode. Most Unix tools which are often used to manipulate filenames (for example sed
, basename
, sort
, etc.) are text processing tools. However, Unix path names are not really text. Consider a path name /aaa/bbb/ccc. The /aaa directory and its bbb subdirectory can in general be created by different users with different environments. That means these users could have a different locale setup, and that means that aaa and bbb do not even necessarily have to have the same character encoding. For example, aaa could be in UTF-8 and bbb in Shift JIS. As a result, an absolute path name in a Unix system may not be correctly processable as text under a single character encoding. Tools which rely on their input being text may fail on such strings.
One workaround for this problem is to run such tools in the C locale, which essentially processes the bytes of the input as-is. However, this will change the behavior of the tools in ways the user may not expect (for example, some of the user's expectations about case-folding behavior may not be met).
References
^ "GNU Core Utilities Frequently Asked Questions". Retrieved December 7, 2015..mw-parser-output cite.citation{font-style:inherit}.mw-parser-output q{quotes:"""""""'""'"}.mw-parser-output code.cs1-code{color:inherit;background:inherit;border:inherit;padding:inherit}.mw-parser-output .cs1-lock-free a{background:url("//upload.wikimedia.org/wikipedia/commons/thumb/6/65/Lock-green.svg/9px-Lock-green.svg.png")no-repeat;background-position:right .1em center}.mw-parser-output .cs1-lock-limited a,.mw-parser-output .cs1-lock-registration a{background:url("//upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Lock-gray-alt-2.svg/9px-Lock-gray-alt-2.svg.png")no-repeat;background-position:right .1em center}.mw-parser-output .cs1-lock-subscription a{background:url("//upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Lock-red-alt-2.svg/9px-Lock-red-alt-2.svg.png")no-repeat;background-position:right .1em center}.mw-parser-output .cs1-subscription,.mw-parser-output .cs1-registration{color:#555}.mw-parser-output .cs1-subscription span,.mw-parser-output .cs1-registration span{border-bottom:1px dotted;cursor:help}.mw-parser-output .cs1-hidden-error{display:none;font-size:100%}.mw-parser-output .cs1-visible-error{font-size:100%}.mw-parser-output .cs1-subscription,.mw-parser-output .cs1-registration,.mw-parser-output .cs1-format{font-size:95%}.mw-parser-output .cs1-kern-left,.mw-parser-output .cs1-kern-wl-left{padding-left:0.2em}.mw-parser-output .cs1-kern-right,.mw-parser-output .cs1-kern-wl-right{padding-right:0.2em}
^ Differences Between xargs and GNU Parallel. GNU.org. Accessed February 2012.
^ Cosmin Stejerean. "Things you (probably) didn't know about xargs". Retrieved December 7, 2015.
External links
: construct argument lists and invoke utility – Commands & Utilities Reference, The Single UNIX Specification, Issue 7 from The Open Group
- Linux Xargs Command Tutorial With Examples
Manual pages
– GNU Findutils reference
: construct argument list(s) and execute utility – FreeBSD General Commands Manual
: construct argument list(s) and execute utility – NetBSD General Commands Manual
: construct argument list(s) and execute utility – OpenBSD General Commands Manual
: construct argument lists and invoke utility – Solaris 10 User Commands Reference Manual