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 | xargsfind . -name "*.log" | xargs rm — Find files and pass them as arguments to rm.
find /var/log -name "*.log" -mtime +30 | xargs rmcat list.txt | xargs <command> — Read arguments from a file (one per line or space-separated).
cat servers.txt | xargs -I{} ssh {} uptimeControlling Arguments
xargs -n <max> — Use at most max arguments per command invocation.
echo "a b c d e f" | xargs -n 2 echoxargs -L <lines> — Use at most the given number of input lines per command invocation.
cat urls.txt | xargs -L 1 curl -Oxargs -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' rmxargs -0 — Use null character as delimiter. Pairs with find -print0 for safe filename handling.
find . -name "*.tmp" -print0 | xargs -0 rmParallel 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 1Safe Execution
xargs -p — Prompt for confirmation before running each command.
find . -name "*.bak" | xargs -p rmxargs -t — Print each command to stderr before executing it (trace mode).
cat files.txt | xargs -t rmxargs --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 rmfind . -name "*.tmp" -print0 | xargs -0 rm — Safe handling of filenames with spaces, quotes, or special characters.
find /data -name "*.log" -print0 | xargs -0 gzipxargs -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 stopgit diff --name-only | xargs <command> — Run a command on all files changed in git.
git diff --name-only | xargs prettier --writeseq 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
- GNU findutils: xargs options – official reference for all xargs options
- Wikipedia: xargs – background and cross-platform notes on xargs