xargs
xargs builds command lines from standard input. Master batching, parallel execution, and safe handling of special characters.
Basic Syntax
command | xargs [options] command_to_run
xargs reads items from stdin and passes them as arguments to a command.
Simple Usage
Default Behavior
echo "file1 file2 file3" | xargs rm
# Equivalent to: rm file1 file2 file3
From File
cat files.txt | xargs rm
xargs rm < files.txt
With find
find . -name "*.tmp" | xargs rm
Placeholder (-I)
Use -I{} to specify where arguments go:
cat urls.txt | xargs -I{} curl -O {}
# Process each line as argument
cat hosts.txt | xargs -I{} ssh {} "uptime"
# Rename files
ls *.txt | xargs -I{} mv {} {}.bak
You can use any placeholder:
cat items.txt | xargs -I@ echo "Processing: @"
Null Delimiter (-0)
Handle filenames with spaces, quotes, newlines:
# find outputs null-terminated
find . -name "*.log" -print0 | xargs -0 rm
# Input with nulls
printf "file one\0file two\0" | xargs -0 echo
Always use -print0 with find and -0 with xargs for safety.
|
Batching
Arguments per Command (-n)
echo "a b c d e f" | xargs -n2 echo
# a b
# c d
# e f
# Process 100 files at a time
find . -name "*.log" -print0 | xargs -0 -n100 gzip
Lines per Command (-L)
cat multiline.txt | xargs -L1 process_line
Parallel Execution (-P)
# Run 4 processes in parallel
cat urls.txt | xargs -P4 -I{} curl -O {}
# Find and compress in parallel
find . -name "*.log" -print0 | xargs -0 -P4 gzip
# Ping multiple hosts
cat hosts.txt | xargs -P10 -I{} ping -c1 {}
Combine with Batching
# 4 parallel processes, 10 files each
find . -name "*.jpg" -print0 | xargs -0 -P4 -n10 convert_images
Safety Options
No Run If Empty (-r)
# Don't run if no input
find . -name "*.nonexistent" | xargs -r rm
Prompt Before Execute (-p)
find . -name "*.bak" | xargs -p rm
# rm file1.bak file2.bak ?...y
Verbose (-t)
echo "a b c" | xargs -t echo
# echo a b c
# a b c
Max Arguments (-s)
# Limit total command line size (bytes)
cat huge_list.txt | xargs -s 1024 echo
Custom Delimiter (-d)
# Newline delimiter (default for most cases)
cat list.txt | xargs -d'\n' process
# Comma delimiter
echo "a,b,c" | xargs -d',' echo
# a b c
Infrastructure Patterns
Bulk File Operations
# Delete old logs
find /var/log -name "*.log" -mtime +30 -print0 | xargs -0 rm -v
# Compress logs
find . -name "*.log" -print0 | xargs -0 -P4 gzip
# Change ownership
find /app -type f -print0 | xargs -0 chown appuser:appgroup
Network Operations
# Ping multiple hosts
cat hosts.txt | xargs -P10 -I{} ping -c1 -W1 {}
# Check SSH connectivity
cat hosts.txt | xargs -P5 -I{} ssh -o ConnectTimeout=5 {} "hostname"
# Parallel curl
cat urls.txt | xargs -P4 -I{} curl -s -o /dev/null -w "%{http_code} {}\n" {}
Git Operations
# Stage specific files
git diff --name-only | xargs git add
# Remove untracked files
git ls-files --others --exclude-standard | xargs rm
# Grep in tracked files
git ls-files | xargs grep "TODO"
Docker/Podman
# Stop all containers
docker ps -q | xargs docker stop
# Remove all images
docker images -q | xargs docker rmi
# Remove dangling images
docker images -f "dangling=true" -q | xargs docker rmi
Kubernetes
# Delete pods matching pattern
kubectl get pods | awk '/pattern/ {print $1}' | xargs kubectl delete pod
# Get logs from multiple pods
kubectl get pods -o name | xargs -I{} kubectl logs {}
# Exec on multiple pods
kubectl get pods -o name | xargs -P4 -I{} kubectl exec {} -- date
Process Management
# Kill processes by pattern
pgrep -f "pattern" | xargs kill
# Nice all processes for user
pgrep -u jdoe | xargs renice 10
Batch API Calls
# ISE: Get endpoint details
cat macs.txt | xargs -P5 -I{} netapi ise ers endpoint-mac {}
# Parallel API queries
cat ids.txt | xargs -P10 -I{} curl -s "https://api.example.com/item/{}"
File Processing
# Convert images
find . -name "*.png" -print0 | xargs -0 -P4 -I{} convert {} -resize 50% {}
# Extract text from PDFs
find . -name "*.pdf" -print0 | xargs -0 -I{} pdftotext {} {}.txt
# Run linter on files
find . -name "*.py" -print0 | xargs -0 -P4 pylint
Backup Patterns
# Backup specific files
cat backup-list.txt | xargs -I{} cp {} /backup/
# rsync multiple sources
cat sources.txt | xargs -I{} rsync -av {} /backup/
Combining with awk
# Extract field, then process
ps aux | awk '$1=="jdoe" {print $2}' | xargs kill
# Filter then execute
cat data.csv | awk -F, '$3>100 {print $1}' | xargs process
Building Complex Commands
With sh -c
# When you need shell features
cat files.txt | xargs -I{} sh -c 'echo "Processing {}"; cat {} | wc -l'
# With variables
cat hosts.txt | xargs -I{} sh -c 'echo "$HOST: {}"; ssh {} uptime' _ {}
Multiple Commands
# Chain commands per item
cat files.txt | xargs -I{} sh -c 'cp {} /backup/ && rm {}'
Error Handling
Exit on Error
# Default: continues on error
cat files.txt | xargs rm
# Stop on first error (with sh -c)
cat files.txt | xargs -I{} sh -c 'rm {} || exit 255'
Check Exit Status
find . -name "*.test" -print0 | xargs -0 -I{} sh -c '
if ! test_command {}; then
echo "FAILED: {}"
exit 1
fi
'
Performance Comparison
# Slow: one process per file
find . -name "*.log" -exec gzip {} \;
# Medium: batch to single gzip
find . -name "*.log" -exec gzip {} +
# Fast: parallel gzip
find . -name "*.log" -print0 | xargs -0 -P4 gzip
Common Mistakes
Spaces in Filenames
# WRONG: Breaks on spaces
find . -name "*.txt" | xargs rm
# RIGHT: Null-terminated
find . -name "*.txt" -print0 | xargs -0 rm
Missing -I with Complex Commands
# WRONG: Arguments at end only
cat hosts.txt | xargs ssh uptime
# RIGHT: Specify position
cat hosts.txt | xargs -I{} ssh {} uptime
Forgetting -r
# WRONG: Runs rm with no arguments (may error)
find . -name "*.nonexistent" | xargs rm
# RIGHT: Don't run if empty
find . -name "*.nonexistent" | xargs -r rm
Quick Reference
# Options
-I{} # Placeholder for argument
-0 # Null delimiter (use with find -print0)
-n N # N arguments per command
-P N # N parallel processes
-r # Don't run if no input
-t # Verbose (print command)
-p # Prompt before each
# Common patterns
find ... -print0 | xargs -0 cmd # Safe file handling
cat list | xargs -I{} cmd {} arg # Per-item with placeholder
cat list | xargs -P4 -I{} cmd {} # Parallel processing
cat list | xargs -n10 cmd # Batch 10 at a time
Key Takeaways
-
-print0 | xargs -0- Always for files (handles spaces) -
-I{}- When argument isn’t at end -
-P N- Parallel execution -
-n N- Batch size control -
-r- Don’t run on empty input -
sh -c- For shell features/multiple commands -
Test with
-tor-p- Before destructive operations
Next Module
Process Substitution - Treat commands as files.