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

  1. -print0 | xargs -0 - Always for files (handles spaces)

  2. -I{} - When argument isn’t at end

  3. -P N - Parallel execution

  4. -n N - Batch size control

  5. -r - Don’t run on empty input

  6. sh -c - For shell features/multiple commands

  7. Test with -t or -p - Before destructive operations

Next Module

Process Substitution - Treat commands as files.