xargs takes what comes down a pipe and hands it to the next command as arguments. Learn how to act on `find` results, when to use `-n`, and how `-I {}` places the value, by running the commands in a real terminal in your browser.
Updated: 2026-09-06
command that lists things | xargs [options] command to run
It rearranges piped input into arguments for the next command.
Some commands read standard input; others only take arguments.
rm is the second kind.
$ find tmp -name '*.tmp'
tmp/cache1.tmp
tmp/cache2.tmp
$ find tmp -name '*.tmp' | rm
rm: missing operand
The list arrived, but rm never looked at it.
With xargs in between, the list becomes arguments.
$ find tmp -name '*.tmp' | xargs rm
$ ls tmp
Gone. That is the whole job of xargs.
By default everything is handed over in one run.
$ ls logs
access.log app.log error.log
$ ls logs | xargs echo
access.log app.log error.log
Which makes counting the results of a find completely natural.
$ find logs -name '*.log' | xargs wc -l
3 logs/app.log
2 logs/access.log
1 logs/error.log
6 total
Paired with grep -l, which prints only the names of matching files, you can act on just the files that contain an error.
$ grep -l ERROR logs/*.log | xargs wc -l
3 logs/app.log
1 logs/error.log
4 total
-n 1 runs the command once per value.
$ echo 'a b c' | xargs -n 1 echo
a
b
c
When the value must go somewhere other than the end, use -I.
$ find logs -name '*.log' | xargs -I {} cp {} backup/
$ ls backup
access.log app.log error.log
Each value is substituted at {}.
Commands like cp, where the order of source and destination is fixed, need this form.
$ ls logs | xargs -I {} echo 'file: {}'
file: access.log
file: app.log
file: error.log
xargs is what you type to feed what you found into what you want done.
| Situation | What to type |
|---|---|
| Delete what you found | find . -name '*.tmp' | xargs rm |
| Count the lines of what you found | find . -name '*.log' | xargs wc -l |
| Act only on matching files | grep -l ERROR *.log | xargs wc -l |
| Copy each one somewhere | ls *.log | xargs -I {} cp {} backup/ |
| See what would be passed | find . -name '*.tmp' | xargs echo |
Check with echo before deleting.
xargs rm asks nothing.
Swapping in xargs echo and reading the list first is the habit worth having.
Spaces in file names break it.
xargs splits on whitespace, so my file.txt arrives as two arguments.
-I {} takes the whole line as one value and avoids that.
An empty list still runs the command once.
$ find . -name 'nope*' | xargs rm
rm: missing operand
With no matches, rm runs with no arguments at all.
One more reason to try destructive pipelines with xargs echo first.
Commands that read standard input do not need it.
grep and sort read input themselves.
Putting xargs in front turns that input into arguments, which means something different.
webterm.appthis site
Terminal Fundamentals
Learn commonly used commands
learn.webterm.appa separate site

Commands stick when they show up in a real sequence of work, not one at a time. There is a course that builds them up in order.
See the course