kmail.at
contact

elsewhere

EnglishEN
← learning

shell · difficulty ◆◆

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.

AI-generated draft · reviewed and editedThis text was generated with AI as a first draft, then reviewed and edited by the author, who holds editorial responsibility for it.

2026-09-23 · 6 min read

$ xargs

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.

Example

$ 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.

Common flags

-n N
use at most N arguments per command line, so the command runs once per chunk of N
-P N
run up to N commands in parallel (great speedup for slow tasks)
-0
read NUL-separated input instead of whitespace — pairs with find -print0
-p
prompt before each command line; handy for a safe dry run
-t
print each command before running it (trace mode)
-r
do 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/

History

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 'extended 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: on Linux the total argument-and-environment space is a fraction of the stack limit, about 2 MiB here — `getconf ARG_MAX` returns 2097152. 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, and `xargs --show-limits` tells you exactly which numbers it is working with: the command buffer it is actually using (131072 bytes on this box) and the much larger ceiling it could use. That is the core batch behavior -n lets you control by hand.

Fun facts

Pros & cons

pros

  • + Batches input to fit the OS argument limit automatically — no 'Argument list too long' failures
  • + -P gives parallel execution with zero extra tooling, a huge speedup on slow per-file jobs
  • + NUL-safe with -0, so it handles awkward filenames correctly
  • + Replaces the slow per-file find -exec for bulk operations

cons

  • − Whitespace splitting by default will mangle filenames with spaces unless you remember -0
  • − Runs commands per chunk, not per line, unless you use -n 1 — easy to misread
  • − A mistyped filter hands the wrong file list to a destructive command with no undo

Takeaways

  1. 1Line-to-args is the whole job: `list | xargs cmd` turns output into command arguments
  2. 2For any file-handling command, always pair `find ... -print0` with `xargs -0`
  3. 3Use -n N to chunk arguments and -P N to parallelize slow per-file work
  4. 4Dry-run first with -p (prompt) or -t (trace) before you hand rm a generated list
  5. 5Batch with find instead of find -exec when you touch thousands of files — it is far faster

Related commands