xargs builds command lines out of piped input. Pipes normally connect stdout to stdin, but many commands want their data as arguments — and that gap between streams and arguments is exactly what xargs bridges.

The basic bridge #

Turn lines into arguments
$ cat urls.txt | xargs curl -s -O
$ ls *.png | xargs -n 1 file

The second example shows -n 1: run the command once per line, one argument at a time. Without it, xargs packs as many arguments per invocation as the command line allows — usually what you want for bulk jobs.

The flags that matter #

FlagEffect
-n NAt most N arguments per run
-I {}Insert each item at {} in a template
-P 4Run 4 commands in parallel
-0NUL-separated input, for find -print0
--no-run-if-emptySkip the run when input is empty

-I {} earns its keep when the argument sits mid-command:

Move every listed file into an archive folder
$ cat keep.txt | xargs -I {} mv {} archive/

find and xargs, properly paired #

The canonical combination — find locates, xargs acts — has one famous trap: filenames with spaces break the naive form. The fix is the NUL-delimited pair:

The safe find-plus-xargs pattern
$ find . -name "*.log" -print0 | xargs -0 -n 1 gzip

-print0 and -0 speak a private delimiter that no filename can contain. See find for the locating half.

Parallelism is the quiet superpower — a four-core machine compressing in parallel:

Compress archives four at a time
$ find . -name "*.tar" -print0 | xargs -0 -P 4 -n 1 gzip -9

For counting and shaping the lines before they become arguments, sort and uniq and grep sit naturally upstream. More assembly-line patterns are in unix pipes in practice, part of the terminal notes.