xargs — build and run commands from input

Take a stream of lines and hand them to another command as arguments.

Every time you type `find . -name '*.log'` and stare at the list, you are one pipe away from doing something useful with it — xargs is the glue that turns that list into another command's arguments.

What it does

xargs reads whitespace-separated items from standard input and appends them as arguments to the command you give it. The simplest form, `printf 'a b c' | xargs echo`, is boring because echo already reads stdin. The magic appears the moment the target command does NOT read stdin: `find ... | xargs rm`. On this box xargs (GNU findutils 4.9.0) turns a stream of filenames into repeated invocations of your command, batching as many items per line as fit before the OS argument limit.

Why it matters

The classic Unix tools — rm, chmod, chown, grep, wc, du — take filenames as arguments, not as stdin. xargs is the duct tape that connects a producer (find, ls, printf, sort, a log file) to a consumer that only accepts command-line arguments. Without it you cannot clean a build directory with find, count the lines in a pile of logs, or batch-delete stale temp files. It is the other half of the pipe story: grep filters a stream, xargs feeds a stream to a command.

When to reach for it

Reach for xargs any time some tool produced a list of files and you want to run a command on each of them. The canonical pairing is find piped into xargs, replacing the slower per-file find -exec. Batch it with -n for chunked work, -P for parallelism, and -0 when filenames might contain spaces or newlines — which on a real server they eventually will.

Examples

printf 'a.txt\nb.txt\nc.txt\n' | xargs cat
apple
banana cherry
one two three four

cat accepts filenames, so xargs appends each input line as an argument and cat prints all three files. The classic line-to-argument bridge.

find . -name '*.txt' | xargs wc -c
  19 ./c.txt
  17 ./d.txt
   6 ./a.txt
  14 ./b.txt
  56 total

find produces one filename per line; xargs hands them all to wc, which totals the byte counts. Real output captured on this box — note find traverses in directory-entry order, not alphabetical.

printf 'one two three four\n' | xargs -n 2 echo
one two
three four

-n 2 splits the input into chunks of at most two arguments each, running the command once per chunk. Great for commands that only accept a fixed number of arguments.

printf 'file one.txt\0file two.txt\0' | xargs -0 -n 1 echo
file one.txt
file two.txt

-0 reads NUL-separated input, so filenames with spaces survive intact. Always pair xargs -0 with the matching find ... -print0 to survive hostile filenames.

Flags

FlagMeaning
-n Nrun the command at most once per N input arguments
-P Nrun up to N commands in parallel (great speedup for slow tasks)
-0read NUL-separated input instead of whitespace — pairs with find -print0
-pprompt before each command line; handy for a safe dry run
-tprint each command before running it (trace mode)
-rdo not run the command at all if input is empty
-I{}run once per input line, substituting {} with the whole line, e.g. ... -I{} cp {} backup/

Origin

xargs has shipped in Unix for decades and today is part of the findutils package (the 4.9.0 on this machine). Its whole reason to exist is the gap between stream tools and argument-taking tools. The name is a contraction of 'executive arguments' — it takes the output of one command and turns it into the arguments of another.

The argument-limit trap

The kernel caps how many arguments a single command can carry (typically around 128 KiB of total arg space). Early xargs existed largely because naive `$(find ...)` substitution blew past that limit and failed with 'Argument list too long'. xargs sidesteps it by automatically splitting input into batches that fit — that is the core batch behavior -n lets you control by hand.

Fun facts

Pros

Cons

Takeaways