The xargs command in Linux

xargs reads items from standard input and uses them as arguments to another command. It bridges a gap in the pipe model: pipes send data to a command's input, but many commands (rm, cp, mkdir) take their operands as arguments instead. xargs converts one into the other, and can parallelize the work with -P.

How xargs works

There is a hard limit on how long a command line may be (ARG_MAX, a couple of megabytes). xargs exists at that boundary: it reads items from stdin and packs them into as few command invocations as fit under the limit — turning "run rm on these 200,000 files" from an "Argument list too long" error into a handful of maximally full executions. It converts a stream into argument lists, which is the missing adapter between pipes and commands that take operands as arguments.

Its historical weakness is tokenization: by default xargs splits on any whitespace and interprets quotes, so filenames with spaces shatter. The modern fix is a different contract — NUL-separated input, produced by find -print0 and consumed with -0, unambiguous because NUL is the one byte a filename cannot contain. Add -P and the same machinery becomes a parallel executor: same batching, N workers. find | xargs -0 -P is a small distributed system in twenty characters.

Syntax

SOMETHING | xargs [OPTIONS] [COMMAND]

Common options

OptionWhat it does
-I {}Placeholder mode: run the command once per item, with {} replaced.
-n NPass at most N items per command invocation.
-P NRun up to N invocations in parallel.
-0Expect NUL-separated input (pairs with find -print0; safe for spaces in names).
-rDon't run at all if input is empty (GNU).
-pPrompt before each invocation.

How to use xargs: examples

$ find . -name "*.tmp" | xargs rm

Delete every .tmp file found. find lists them; xargs feeds them to rm as arguments.

$ find . -name "*.log" -print0 | xargs -0 rm

The safe version: NUL separators survive spaces and newlines in filenames. Make this the habit.

$ cat urls.txt | xargs -n 1 -P 4 wget -q

Download a list of URLs, four in parallel.

$ ls *.jpg | xargs -I {} cp {} backup/

Placeholder mode: run cp once per file, inserting the name where {} appears.

$ echo "dir1 dir2 dir3" | xargs mkdir

Create several directories from a generated list.

Real-world use cases for xargs

Mass operations on find results

Compressing hundreds of old logs: find /var/log -name "*.log" -mtime +30 -print0 | xargs -0 gzip. The -print0/-0 pair makes filenames with spaces safe, and xargs batches them into few gzip invocations instead of hundreds.

A minimal parallel job runner

Processing a list of items with 8 workers: cat items.txt | xargs -n1 -P8 ./process.sh. For embarrassingly parallel work — image conversion, URL checking, per-host commands — this replaces a queue system in one flag.

Pro tips and common mistakes

Frequently asked questions about xargs

Why use xargs instead of find -exec?

find -exec cmd {} \; launches one process per file; xargs batches many files per invocation, which is dramatically faster on thousands of files. (find -exec cmd {} + batches too, and is a fine alternative.)

How do I handle filenames with spaces?

Use the NUL-separated pair: find … -print0 | xargs -0 …. Plain xargs splits on whitespace and will mangle such names.

Can xargs run things in parallel?

Yes — -P N runs up to N invocations concurrently, turning xargs into a minimal parallel job runner: … | xargs -P 8 -n 1 process.

Related commands

rm

Delete files and directories — and understand -r, -f and why there is no trash bin.

grep

Find lines matching a pattern in files or piped input — the workhorse of text search.

find

Locate files anywhere in a directory tree by name, type, size, date — and act on them.

Want to build real fluency? The interactive course takes you through xargs and every other essential command with guided, checked exercises.