xargs — Build Command Lines from Standard Input

Practical guide to xargs: bundle stdin into command arguments, stay safe with -0, use -I {} as a placeholder and run in parallel with -P.

xargs reads data from standard input and builds it into the arguments for another command – turning lists produced by other tools (such as find or grep) into executable commands in one step. That is hugely powerful but also risky: because xargs actually runs the command line it assembles, a careless xargs rm can delete more than you intended. The trickiest part is handling filenames that contain spaces or newlines – for that you combine find ... -print0 with xargs -0, so entries are passed NUL-separated and therefore unambiguous. This guide walks you through the options you actually reach for: from bundling arguments to the -I {} placeholder and parallel execution with -P.

Basic Usage

echo "file1 file2 file3" | xargs rm — Pass input words as arguments to a command.

echo "file1.tmp file2.tmp" | xargs rm

<command> | xargs — Without a command, xargs defaults to echo (combines input into a single line).

cat urls.txt | xargs

find . -name "*.log" | xargs rm — Find files and pass them as arguments to rm.

find /var/log -name "*.log" -mtime +30 | xargs rm

cat list.txt | xargs <command> — Read arguments from a file (one per line or space-separated).

cat servers.txt | xargs -I{} ssh {} uptime

Controlling Arguments

xargs -n <max> — Use at most max arguments per command invocation.

echo "a b c d e f" | xargs -n 2 echo

xargs -L <lines> — Use at most the given number of input lines per command invocation.

cat urls.txt | xargs -L 1 curl -O

xargs -I{} <command> {} — Replace {} with each input item. Runs command once per item.

cat files.txt | xargs -I{} cp {} /backup/

xargs -I@ <command> @ — Use a custom placeholder instead of {}.

ls *.csv | xargs -I@ mv @ processed/

xargs -d '\n' — Use newline as the delimiter (instead of any whitespace).

cat filelist.txt | xargs -d '\n' rm

xargs -0 — Use null character as delimiter. Pairs with find -print0 for safe filename handling.

find . -name "*.tmp" -print0 | xargs -0 rm

Parallel Execution

xargs -P <n> — Run up to n processes in parallel.

cat urls.txt | xargs -P 4 -I{} curl -O {}

xargs -P 0 — Run as many processes in parallel as possible.

find . -name "*.png" -print0 | xargs -0 -P 0 -I{} optipng {}

xargs -n 1 -P <n> — Process one argument at a time with n parallel workers.

cat servers.txt | xargs -n 1 -P 8 ping -c 1

Safe Execution

xargs -p — Prompt for confirmation before running each command.

find . -name "*.bak" | xargs -p rm

xargs -t — Print each command to stderr before executing it (trace mode).

cat files.txt | xargs -t rm

xargs --no-run-if-empty — Do not run the command if there is no input (GNU xargs, -r).

find . -name "*.tmp" | xargs --no-run-if-empty rm

find . -name "*.tmp" -print0 | xargs -0 rm — Safe handling of filenames with spaces, quotes, or special characters.

find /data -name "*.log" -print0 | xargs -0 gzip

xargs -s <size> — Set the maximum command line length in bytes (avoid 'argument list too long').

find . -name "*.txt" | xargs -s 4096 grep 'pattern'

Common Patterns

find . -name "*.jpg" -print0 | xargs -0 -I{} convert {} -resize 50% {} — Process each file individually with a complex command.

find ./images -name "*.jpg" -print0 | xargs -0 -I{} convert {} -resize 800x600 {}

ls *.sql | xargs -I{} mysql -u root dbname < {} — Import multiple SQL files into a database.

ls migrations/*.sql | sort | xargs -I{} mysql -u root mydb < {}

grep -rl "oldtext" . | xargs sed -i 's/oldtext/newtext/g' — Find and replace text across multiple files.

grep -rl "http://" ./src | xargs sed -i 's|http://|https://|g'

docker ps -q | xargs docker stop — Stop all running Docker containers.

docker ps -q | xargs docker stop

git diff --name-only | xargs <command> — Run a command on all files changed in git.

git diff --name-only | xargs prettier --write

seq 1 100 | xargs -P 10 -I{} curl -s "http://api.example.com/page/{}" -o "page-{}.html" — Download 100 pages in parallel with 10 workers.

seq 1 50 | xargs -P 5 -I{} wget -q "http://example.com/img/{}.jpg"

cat hosts.txt | xargs -I{} -P 5 ssh {} 'hostname; uptime' — Run a command on multiple remote hosts in parallel.

cat servers.txt | xargs -I{} -P 10 ssh -o ConnectTimeout=5 {} 'df -h /'

find . -name "*.gz" -mtime +7 -print0 | xargs -0 -r rm -v — Delete old compressed files safely with verbose output.

find /var/log -name "*.gz" -mtime +30 -print0 | xargs -0 -r rm -v

Conclusion

xargs is the glue that turns one command's output into the next command's arguments – indispensable as soon as you want to process lists from find, grep or git. Keep two things in mind: first, always use find ... -print0 | xargs -0 (or -d '\n') whenever filenames might contain spaces, quotes or newlines – otherwise xargs splits them in the wrong places. Second, be careful with destructive commands such as rm: test the pipeline first with xargs -t (which prints the command before running it) or swap the real command for echo before going live. Use -I {} to place the argument anywhere in the command, -P N to parallelise, and -r/--no-run-if-empty to avoid running on empty input.

Further Reading

  • find – searches directory trees for files and provides the ideal input for xargs
  • grep – filters lines by pattern, often the source of xargs argument lists
  • tee – writes a data stream to a file and standard output at the same time