xargs Command: Usage, the -n and -I Options and Using It with find
The xargs command is a Linux tool that turns lines and words received on standard input into arguments for another command and runs it. When we passed three log files found by find to wc through xargs in a working folder on an AlmaLinux 9 server, one file with a space in its name was split in two and caused an error, and with -print0 and -0 the line counts of all three files appeared.
The output below was run inside a working folder under the root account on an AlmaLinux 9.8 server. The name list, logs and temporary files are sample files made for testing, and the IP addresses and working folder paths in them are also example values.
1️⃣ Basic xargs command usage
xargs splits the standard input passed by the previous command on spaces and newlines, and runs the command written after it with those pieces in its argument positions. We checked this with names.txt, which holds one name per line.
cat names.txtalice
bob
carol
dave
erinPassing the output of cat to xargs echo turns the five lines into arguments of a single echo, printed on one line.
cat names.txt | xargs echoalice bob carol dave erinIf you write no command after it, xargs runs echo, so the result is the same.
cat names.txt | xargsalice bob carol dave erinA pipe connects the output of the previous command to the standard input of the next one, so nothing goes into the next command's argument positions. If you only pipe list.txt, which holds three file names, to wc -l, wc counts the 3 lines of the list itself.
cat list.txtlogs/access.log
logs/error.log
tmp/keep.txtcat list.txt | wc -l3With xargs in between, the three names in the list become arguments of wc, and the line count appears for each file.
cat list.txt | xargs wc -l 3 logs/access.log
2 logs/error.log
1 tmp/keep.txt
6 total2️⃣ The xargs -n and -I options
Without options, all input goes into one run of the command, so to repeat the command, use -n to set how many arguments are passed at a time. The figure below shows how the same five names are grouped depending on the option.
-n 1 runs echo for each name, printing five lines.
cat names.txt | xargs -n 1 echoalice
bob
carol
dave
erin-n 2 groups them in twos and passes the one left over on its own.
cat names.txt | xargs -n 2 echoalice bob
carol dave
erinTo see the commands being run, add -t. The command line appears first, with its output below it.
cat names.txt | xargs -t -n 2 echoecho alice bob
alice bob
echo carol dave
carol dave
echo erin
erinIf an argument must go somewhere other than the end of the command, set a placeholder with -I. One line goes in place of {} at a time, and if the same text appears several times, all of them are replaced.
cat names.txt | xargs -I {} echo 'user: {}'user: alice
user: bob
user: carol
user: dave
user: erincat names.txt | xargs -I {} echo '{} -> home/{}'alice -> home/alice
bob -> home/bob
carol -> home/carol
dave -> home/dave
erin -> home/erinYou can make a folder per name in the same way. Create the home folder first, then use -I {} to make a folder per name under it, and five folders appear.
mkdir homecat names.txt | xargs -I {} mkdir home/{}ls homealice bob carol dave erin-I treats one line as one argument, so it cannot be used with -n. When we wrote both, -I was ignored with a warning and {} was printed as literal text.
cat names.txt | xargs -I {} -n 2 echo {}xargs: warning: options --replace and --max-args/-n are mutually exclusive, ignoring previous --replace value
{} alice bob
{} carol dave
{} erin-L groups by line count. If a line holds several words, the words on that line are passed together, and in names.txt, with one name per line, -L 2 gave the same result as -n 2.
cat names.txt | xargs -L 2 echoalice bob
carol dave
erin3️⃣ Combining find and xargs
You do not have to build a name list by hand; you can pass the files found by find straight to xargs. Looking for files ending in .log in the log folder finds three, and one of them has a space in its name.
find /root/work/logs -name '*.log'/root/work/logs/access.log
/root/work/logs/error.log
/root/work/logs/old access.logWhen this list went straight to xargs wc -l, the name with a space split into old and access.log, giving two error lines, and the total was 5 lines from only two files.
find /root/work/logs -name '*.log' | xargs wc -l 3 /root/work/logs/access.log
2 /root/work/logs/error.log
wc: /root/work/logs/old: No such file or directory
wc: access.log: No such file or directory
5 totalfind's -print0 separates names with the null character instead of a newline, and xargs's -0 splits arguments only on that null character. Using both gives the line counts of all three files, including the one with a space.
find /root/work/logs -name '*.log' -print0 | xargs -0 wc -l 3 /root/work/logs/access.log
2 /root/work/logs/error.log
1 /root/work/logs/old access.log
6 totalfind's -exec option does the same job. With + after {}, the found files are passed at once, so the result is the same, and find passes spaces in file names as they are. xargs also accepts output from commands other than find, so use it when input does not come from find alone, or when you need to set how many items are passed at a time (-n) or how many run at once (-P).
find /root/work/logs -name '*.log' -exec wc -l {} + 3 /root/work/logs/access.log
2 /root/work/logs/error.log
1 /root/work/logs/old access.log
6 totalTo pick only the found files containing a string, add grep -l after xargs. Two files contained wp-login: the access log and the error log.
find /root/work/logs -name '*.log' -print0 | xargs -0 grep -l wp-login/root/work/logs/access.log
/root/work/logs/error.log4️⃣ Deleting files with the xargs command
With rm after xargs, the found files are deleted at once, so check which files will be passed before deleting. Putting echo in front of rm prints only the command line that would run, and the files stay in place.
find /root/work/tmp -name '*.tmp' -print0 | xargs -0 echo rmrm /root/work/tmp/cache-a.tmp /root/work/tmp/cache-b.tmp /root/work/tmp/cache-c.tmpls tmpcache-a.tmp cache-b.tmp cache-c.tmp keep.txtWith -p, xargs asks whether to run each command. Entering n deletes nothing, so the three temporary files stay.
find /root/work/tmp -name '*.tmp' -print0 | xargs -0 -p rmrm /root/work/tmp/cache-a.tmp /root/work/tmp/cache-b.tmp /root/work/tmp/cache-c.tmp?...nls tmpcache-a.tmp cache-b.tmp cache-c.tmp keep.txtEntering y deletes the three files, leaving only keep.txt.
find /root/work/tmp -name '*.tmp' -print0 | xargs -0 -p rmrm /root/work/tmp/cache-a.tmp /root/work/tmp/cache-b.tmp /root/work/tmp/cache-c.tmp?...yls tmpkeep.txtIf input is empty, xargs runs the command once with no arguments. Passing an empty file runs rm with no arguments and gives the [rm: missing operand] error; with -r, the command does not run at all.
cat empty.txt | xargs rmrm: missing operand
Try 'rm --help' for more information.cat empty.txt | xargs -r rm5️⃣ xargs parallel execution, delimiters and options
🔲 Parallel execution and delimiters
When commands run one at a time, the time grows with the number of targets. -P sets how many commands run at once. Four sleeps waiting 1, 2, 3 and 4 seconds took 10 seconds one after another, and finished in 4 seconds, the longest one, when run together with -P 4.
time seq 1 4 | xargs -n 1 sleep
real 0m10.007s
user 0m0.004s
sys 0m0.003stime seq 1 4 | xargs -n 1 -P 4 sleep
real 0m4.005s
user 0m0.001s
sys 0m0.006sIf input is split by a symbol rather than newlines or spaces, set the delimiter with -d. Splitting three comma-joined names with -d , prints one line per name.
printf 'alice,bob,carol' | xargs -d , -n 1 echoalice
bob
carolTo read from a file instead of standard input, give the file name to -a. The five names in names.txt went to echo without a pipe.
xargs -a names.txt echoalice bob carol dave erin🔲 xargs command options
📌 Main options: results from this article
| Option | Task | Result in this article | |
|---|---|---|---|
| -n | Sets how many arguments are passed to one run of the command | The five names are grouped in twos by -n 2, and echo runs three times | |
| -I | Puts one line at a time into the placeholder and runs per line | A name goes in place of {}; written with -n, -I is ignored with a warning | |
| -L | Sets how many lines are passed to one run of the command | In a file with one name per line, same result as -n 2 | |
| -t | Prints the command line before running it | The command line appears before the output | |
| -0 | Splits input only on the null character (with find -print0) | Without it, names with spaces split, giving two error lines; with it, all three files show 6 lines | |
| -p | Asks whether to run each command | n leaves them in place; y deletes the three files | |
| -r | Does not run the command if input is empty | Without it, [rm: missing operand]; with it, nothing runs | |
| -P | Sets how many commands run at once | Four sleeps take 10 seconds in turn, 4 seconds with -P 4 | |
| -d | Sets the delimiter that splits input | -d , prints one line per name | |
| -a | Reads input from a file instead of standard input | The five names in names.txt go to a single echo |
📎 Other options: per the official manual
| Option | Task | |
|---|---|---|
| -s | Sets the maximum characters on one command line | |
| -x | Beyond the -s size, ends without running | |
| -E | Stops reading further input on reaching a line with only this text | |
| -o | Reopens the terminal as the command's standard input (for interactive programs) | |
| --process-slot-var | Puts a different number in an environment variable for each command running at once |
🔲 xargs command simulator
In the simulator below, you can type xargs and find commands yourself on the same test files.
🔢 FAQ & Recommended Content
String search
Linux grep command
The grep command finds lines matching strings and regular expressions inside files. Use it to search several files passed through xargs at once.
Deleting files
Linux rm command
An article on the rm command, which deletes files and folders, and the dangers of the -rf option. Check the options before putting rm after xargs.
Ending processes
Linux kill command
The kill command sends a signal to a process ID to end it. Use it next when you pass a list of process IDs through xargs to end them.
ℹ️ Affiliate Disclosure
This site's content contains affiliate links. When a visitor buys a product or service through one of them, the site receives a commission from the seller. The amount the buyer pays(it goes down during event discounts ↓)does not go up. Posted prices, discounts, and stock reflect the time of writing and may differ, so confirm with the seller before buying. Products are chosen and reviewed by our own standards, and commissions do not affect the order or content of reviews.