Where to start First steps track · 15 stages
Linux Labs

xargs — building arguments from a stream

3 min GNU findutils

Turns stdin lines into a command's arguments; without -0, file names with spaces and newlines break the parsing.

Cheat sheet

5 commands Printable version
  • find . -name '*.x' -print0 | xargs -0 rm safe (spaces)
  • ... | xargs -I{} cp {} /dst/ substitute {}
  • ... | xargs -P4 -n1 cmd in parallel
  • ... | xargs -rt cmd skip if empty + show it
  • ... | xargs -n1 one argument at a time

Overview

xargs takes lines from stdin and passes them as a command's arguments. Needed when a command doesn't read stdin but expects arguments instead (like rm, chmod).

bash
echo "a b c" | xargs touch        # creates files a, b, c
find . -name '*.tmp' | xargs rm   # delete what was found

Options

7

Without -0, xargs splits the input on spaces and newlines — a file name with a space turns into two separate arguments. The safe path is a NUL delimiter on both sides of the pipeline: find -print0 (or grep -Z) together with xargs -0. -I {} implicitly limits the call to one argument at a time, like -n1, because you can't substitute several values into one placeholder at once.

bash
... | xargs -n1 cmd               # one argument per call
... | xargs -I{} cp {} /backup/   # substitute {} (often -I implies -n1)
... | xargs -P4 -n1 cmd           # in parallel, 4 processes
cat urls.txt | xargs -P8 -I{} curl -sO {}   # download 8 in parallel
... | xargs -rt cmd               # skip if empty + show the command
Option What it does Example
-0 Input is NUL-delimited — safe for names with spaces (pairs with find -print0). find . -name '*.log' -print0 | xargs -0 rm
-n N Pass at most N arguments per invocation of the command. ... | xargs -n1 cmd
-I {} Substitute the argument anywhere in the command, one at a time. ... | xargs -I{} cp {} /backup/
-r --no-run-if-empty Do not run the command at all if there is no input. ... | xargs -r cmd
-P N Run up to N processes in parallel. cat urls.txt | xargs -P8 -I{} curl -sO {}
-t Print the assembled command before running it — useful for debugging. ... | xargs -t cmd
-a FILE Read arguments from a file instead of stdin. xargs -a urls.txt wget

Nothing found. Try a shorter query.

Recipes

1

Safe with file names

Spaces and newlines in file names break a naive xargs. The right way is a NUL delimiter:

bash
find . -name '*.log' -print0 | xargs -0 rm        # -print0 + -0
grep -rlZ "TODO" . | xargs -0 sed -i 's/TODO/DONE/g'   # grep's -Z + xargs's -0

Troubleshooting

5

Names with spaces get cut up

find ... -print0 | xargs -0 (or find -exec cmd {} +, see find).

xargs ran on empty input and made a mess

Add -r (--no-run-if-empty) — don't run the command with no arguments.

"Argument list too long" / one call with a huge number of arguments

xargs splits into batches itself (a system limit); to control it, use -n N. An alternative is find -exec cmd {} + (which also groups them).

Need to insert the argument somewhere other than the end

xargs -I{} cmd ... {} ... — {} is substituted at the given spot (one call at a time).

Parallel output gets interleaved

With -P, lines from different processes interleave. Log to separate files, or use GNU parallel (which can order the output).

See also

  • find — Finding files by name, size, time, permissions; acting on the results.
  • grep — Searching lines by pattern; regexes, recursion, context.
  • files-basics — Navigation and files — ls, cd, cp, mv, rm, cat, less, head, tail, copy-paste in the terminal.
Loading…