Skip to content

xargs - Street Ops

Real-world xargs patterns pulled from production incidents, migrations, and daily operations.

Quick Diagnosis Commands

# Check ARG_MAX on this system (max bytes for a single command line)
getconf ARG_MAX

# See how many arguments xargs will batch by default
echo | xargs --show-limits 2>&1 | head -5

# Test what xargs will do without executing (dry run)
echo "a b c d" | xargs -t -n 2 echo 2>&1

# Count items that will be processed
find /var/log -name '*.gz' | wc -l

# Verify null-delimited pipeline works end to end
find /tmp -name '*.tmp' -print0 | xargs -0 -t echo 2>&1 | head

Common Scenarios

Bulk File Operations

Mass rename during a migration

# Rename all .yml files to .yaml across a project
find /opt/app/config -name '*.yml' -print0 | \
  xargs -0 -I {} bash -c 'mv "{}" "${1%.yml}.yaml"' _ {}

# Add a date prefix to all files in a directory
ls /data/exports/*.csv | \
  xargs -I {} bash -c 'mv "{}" "$(dirname {})/$(date +%Y%m%d)_$(basename {})"'

# Flatten a nested directory structure (move all files to one dir)
find /data/nested -type f -print0 | xargs -0 -I {} mv {} /data/flat/

Bulk permission fixes after a bad deploy

Under the hood: xargs without -print0/-0 splits on whitespace and newlines. A filename containing a space like my file.log becomes two arguments. Always pair find -print0 with xargs -0 in production scripts -- this is the only safe combination for arbitrary filenames.

# Fix file permissions (files should be 644, not 755)
find /var/www/html -type f -print0 | xargs -0 chmod 644

# Fix directory permissions
find /var/www/html -type d -print0 | xargs -0 chmod 755

# Fix ownership recursively (faster than chown -R for large trees)
find /opt/app -print0 | xargs -0 chown appuser:appgroup

# Remove setuid/setgid bits from uploaded files
find /data/uploads -type f \( -perm -4000 -o -perm -2000 \) -print0 | \
  xargs -0 chmod ug-s

Disk space recovery

# Find and remove core dumps
find / -name 'core' -o -name 'core.*' -o -name '*.core' 2>/dev/null | \
  xargs -r rm -f

# Truncate (not delete) large log files to reclaim space without breaking open handles
find /var/log -name '*.log' -size +1G -print0 | \
  xargs -0 -I {} truncate -s 0 {}

# Remove old rotated logs
find /var/log -name '*.gz' -mtime +30 -print0 | xargs -0 rm -f

# Find large files consuming disk and list them by size
find / -xdev -type f -size +500M -print0 2>/dev/null | \
  xargs -0 ls -lhS | head -20

Parallel API Calls

Health checking a microservice fleet

# Check health endpoints across all services
kubectl get svc -A -o jsonpath='{range .items[*]}{.metadata.name}.{.metadata.namespace}.svc.cluster.local{"\n"}{end}' | \
  xargs -P 20 -I {} curl -sf -m 3 -o /dev/null -w "%{http_code} {}\n" http://{}:8080/health 2>/dev/null

# Parallel endpoint validation with timeout and retry
cat api-endpoints.txt | xargs -P 10 -I {} bash -c '
  for attempt in 1 2 3; do
    code=$(curl -sf -m 5 -o /dev/null -w "%{http_code}" "{}" 2>/dev/null)
    if [ "$code" = "200" ]; then
      echo "OK {} ($code)"
      exit 0
    fi
    sleep 1
  done
  echo "FAIL {} (last: ${code:-timeout})"
'

Bulk webhook testing

# Send test payloads to multiple webhook endpoints
cat webhook-urls.txt | xargs -P 5 -I {} \
  curl -sf -X POST -H "Content-Type: application/json" \
  -d '{"event":"test","timestamp":"2026-03-19T00:00:00Z"}' \
  -w "%{http_code} {}\n" -o /dev/null {} 2>/dev/null

Parallel DNS lookups

# Resolve all hostnames in a list, 20 at a time
cat hostnames.txt | xargs -P 20 -I {} bash -c '
  ip=$(dig +short {} A | head -1)
  echo "{}: ${ip:-NXDOMAIN}"
'

Mass Process Management

Kill runaway processes

# Kill all processes matching a pattern (safer than killall)
pgrep -f 'stuck_worker' | xargs -r kill -TERM

# Force kill after grace period
pgrep -f 'stuck_worker' | xargs -r kill -TERM
sleep 10
pgrep -f 'stuck_worker' | xargs -r kill -KILL

# Kill all processes owned by a specific user
pgrep -u abandoned_user | xargs -r kill -TERM

# Kill all processes listening on a specific port range
ss -tlnp | awk '/:(808[0-9])/ {print $NF}' | grep -oP 'pid=\K[0-9]+' | \
  sort -u | xargs -r kill -TERM

Container cleanup during incidents

# Stop all containers in a specific network
docker network inspect bridge -f '{{range .Containers}}{{.Name}} {{end}}' | \
  tr ' ' '\n' | grep -v '^$' | xargs -r -I {} docker stop {}

# Remove all containers with a specific label
docker ps -aq --filter label=environment=staging | xargs -r docker rm -f

# Restart all containers that exited with non-zero status
docker ps -aq --filter status=exited --filter exited=1 | \
  xargs -r -I {} docker start {}

Log Processing Pipelines

Extract and aggregate error patterns

# Find all error log files from the last 24 hours and extract unique errors
find /var/log/app -name '*.log' -mtime -1 -print0 | \
  xargs -0 grep -h 'ERROR' | \
  awk '{$1=$2=""; print}' | sort | uniq -c | sort -rn | head -20

# Search across compressed log archives in parallel
find /var/log/archive -name '*.gz' -print0 | \
  xargs -0 -P 8 -I {} zgrep -l 'OutOfMemoryError' {}

# Aggregate request counts by endpoint from access logs
find /var/log/nginx -name 'access.log*' -not -name '*.gz' -print0 | \
  xargs -0 awk '{print $7}' | sort | uniq -c | sort -rn | head -30

# Extract slow queries from multiple database log files
find /var/log/postgresql -name '*.log' -print0 | \
  xargs -0 grep -h 'duration:' | \
  awk -F'duration: ' '$2+0 > 1000 {print}' | sort -t: -k2 -rn | head -20

Building incident timelines

# Search all log sources for a specific request ID
find /var/log -name '*.log' -mtime -1 -print0 | \
  xargs -0 -P 8 grep -l 'req-abc123' | \
  xargs -I {} sh -c 'echo "=== {} ==="; grep "req-abc123" {} | head -5'

# Correlate events across services within a time window
find /var/log/services -name '*.log' -print0 | \
  xargs -0 grep -h '2026-03-19T14:3[0-5]' | sort -t'T' -k2

Bulk Permission and Ownership Changes

Post-deploy permission hardening

# Ensure no world-writable files exist in the application directory
find /opt/app -type f -perm -002 -print0 | xargs -0 -r chmod o-w

# Set correct ownership for uploaded content
find /data/uploads -not -user www-data -print0 | \
  xargs -0 -r chown www-data:www-data

# Remove group write from config files
find /etc/myapp -name '*.conf' -print0 | xargs -0 chmod g-w

# Fix SELinux contexts after a file migration
find /var/www/html -print0 | xargs -0 restorecon -v

Database Operations

Bulk table maintenance

# VACUUM ANALYZE all tables in a PostgreSQL database
psql -d production -t -c \
  "SELECT schemaname||'.'||tablename FROM pg_tables WHERE schemaname NOT IN ('pg_catalog','information_schema')" | \
  sed 's/^ *//' | grep -v '^$' | \
  xargs -I {} psql -d production -c "VACUUM ANALYZE {};"

# Export each table to a separate CSV
psql -d analytics -t -c \
  "SELECT tablename FROM pg_tables WHERE schemaname='public'" | \
  sed 's/^ *//' | grep -v '^$' | \
  xargs -P 4 -I {} psql -d analytics -c "\COPY {} TO '/backup/csv/{}.csv' CSV HEADER"

# Run OPTIMIZE on all MySQL tables
mysql -Nse "SELECT CONCAT(table_schema,'.',table_name) FROM information_schema.tables WHERE table_schema='mydb'" | \
  xargs -I {} mysql -e "OPTIMIZE TABLE {};"

Bulk Redis operations

# Delete all keys matching a pattern (safer than FLUSHDB)
redis-cli --scan --pattern 'cache:session:*' | xargs -n 100 redis-cli DEL

# Get TTL for all keys matching a pattern
redis-cli --scan --pattern 'rate_limit:*' | \
  xargs -I {} redis-cli TTL {} | paste - -

# Dump key sizes for capacity planning
redis-cli --scan --pattern '*' | \
  xargs -I {} redis-cli DEBUG OBJECT {} 2>/dev/null | \
  grep -oP 'serializedlength:\K[0-9]+' | \
  awk '{sum+=$1; count++} END {printf "Keys: %d, Total: %.2f MB, Avg: %.0f bytes\n", count, sum/1048576, sum/count}'

Operational Patterns

Safe Dry Run Pattern

Always test destructive operations before executing:

# Step 1: See what will be affected
find /data -name '*.tmp' -mtime +7 -print0 | xargs -0 ls -la

# Step 2: Count items
find /data -name '*.tmp' -mtime +7 | wc -l

# Step 3: Execute with trace
find /data -name '*.tmp' -mtime +7 -print0 | xargs -0 -t rm -f

Batched Operations with Progress

# Process in batches with a counter
total=$(find /data -name '*.raw' | wc -l)
find /data -name '*.raw' -print0 | xargs -0 -n 1 -I {} bash -c '
  count=$((count + 1))
  echo "[$count] Processing: {}"
  convert {} {}.processed
'

# Parallel with per-item status
find /data/images -name '*.png' -print0 | \
  xargs -0 -P 8 -I {} bash -c '
    if convert "{}" -resize 800x600 "/output/$(basename {})"; then
      echo "OK: {}"
    else
      echo "FAIL: {}" >&2
    fi
  '

Retry Wrapper for Unreliable Operations

# Retry each item up to 3 times on failure
cat urls.txt | xargs -P 5 -I {} bash -c '
  for i in 1 2 3; do
    if curl -sf -m 10 -o "/data/$(basename {})" "{}"; then
      exit 0
    fi
    echo "Retry $i for {}" >&2
    sleep $((i * 2))
  done
  echo "FAILED after 3 attempts: {}" >&2
  exit 1
'

Conditional Execution

# Only process files that meet a condition
find /data -name '*.csv' -print0 | xargs -0 -I {} bash -c '
  lines=$(wc -l < "{}")
  if [ "$lines" -gt 1000 ]; then
    echo "Processing {} ($lines lines)"
    python3 /opt/scripts/analyze.py "{}"
  fi
'

# Process only files not already in the destination
find /source -name '*.dat' -print0 | xargs -0 -I {} bash -c '
  dest="/dest/$(basename {})"
  if [ ! -f "$dest" ]; then
    cp "{}" "$dest"
    echo "Copied: {}"
  fi
'

Pipeline with Error Collection

# Run operations and collect failures for review
find /data -name '*.json' -print0 | \
  xargs -0 -P 4 -I {} bash -c '
    if ! python3 validate.py "{}" 2>/dev/null; then
      echo "{}"
    fi
  ' > /tmp/failed-files.txt

echo "$(wc -l < /tmp/failed-files.txt) files failed validation"
cat /tmp/failed-files.txt

Kubernetes Operational Patterns

# Evict all pods from a node before maintenance
kubectl get pods --field-selector spec.nodeName=worker-03 -o name | \
  xargs -I {} kubectl delete {} --grace-period=30

# Annotate all deployments in a namespace
kubectl get deploy -n production -o name | \
  xargs -I {} kubectl annotate {} -n production last-audit="2026-03-19" --overwrite

# Scale down all non-critical deployments (matching a label)
kubectl get deploy -l tier=non-critical -o name | \
  xargs -I {} kubectl scale {} --replicas=0

# Collect logs from all pods matching a label
kubectl get pods -l app=api-gateway -o name | \
  xargs -P 4 -I {} bash -c 'kubectl logs {} --tail=50 > /tmp/logs/$(echo {} | tr "/" "_").log'

# Force delete stuck terminating pods
kubectl get pods --field-selector status.phase=Terminating -o name 2>/dev/null | \
  xargs -r -I {} kubectl delete {} --grace-period=0 --force

Git Operations

# Remove all merged branches except main
git branch --merged main | grep -v 'main' | xargs -r git branch -d

# Find all repos with uncommitted changes
find /workspace -name '.git' -type d | \
  xargs -I {} bash -c 'cd "{}/.." && if [ -n "$(git status --porcelain)" ]; then echo "DIRTY: $(pwd)"; fi'

# Bulk clone repos from a list
cat repos.txt | xargs -P 4 -I {} git clone {}