← All cheat sheets

XARGS

Authorized use only. Offensive reference for systems you own or are explicitly permitted to test. You are responsible for staying within the law.

xargs builds and executes commands from standard input.
Converts input into arguments for other commands.

BASIC USAGE#

echo "file.txt" | xargs cat          # Use input as argument
find . -name "*.txt" | xargs wc -l   # Count lines in found files
ls | xargs echo                      # List files on one line

BASIC OPTIONS#

xargs -n N                # Max N arguments per command
xargs -I {}               # Replace {} with input
xargs -d 'delim'          # Use custom delimiter
xargs -0                  # Null delimiter (for find -print0)
xargs -p                  # Prompt before execution
xargs -t                  # Print command before execution
xargs -r                  # Don't run if input is empty

ARGUMENT CONTROL#

# Default: as many args as possible
echo "a b c d e" | xargs echo
# Output: a b c d e

# One argument per execution
echo "a b c d e" | xargs -n 1 echo
# Output: a
#         b
#         c
#         d
#         e

# Two arguments per execution
echo "a b c d e f" | xargs -n 2 echo
# Output: a b
#         c d
#         e f

PLACEHOLDER REPLACEMENT#

# -I: Replace string with input
ls | xargs -I {} echo "File: {}"

# Multiple uses of placeholder
ls | xargs -I {} cp {} {}.backup

# Custom placeholder
ls | xargs -I FILE mv FILE FILE.old

# With find
find . -name "*.txt" | xargs -I {} cp {} /backup/

DELIMITER OPTIONS#

# Default delimiter: whitespace and newlines
echo "a b c" | xargs echo           # a b c

# Custom delimiter
echo "a:b:c" | xargs -d ':' echo    # a b c

# Null delimiter (for filenames with spaces)
find . -name "*.txt" -print0 | xargs -0 rm

# Newline delimiter
cat files.txt | xargs -d '\n' rm

SAFETY OPTIONS#

# Prompt before each command
find . -name "*.log" | xargs -p rm

# Print command (dry run style)
find . -name "*.log" | xargs -t rm

# Don't run if empty input
find . -name "*.xyz" | xargs -r rm
# Without -r, would run: rm (with no args)

PARALLEL EXECUTION#

# Run N processes in parallel
find . -name "*.png" | xargs -P 4 -I {} convert {} -resize 50% {}

# Max parallel (use all CPUs)
find . -name "*.gz" | xargs -P 0 gunzip

# Combine with -n
cat urls.txt | xargs -P 10 -n 1 curl -O

LIMITING ARGUMENTS#

# Max arguments per line
echo "1 2 3 4 5" | xargs -n 2 echo
# 1 2
# 3 4
# 5

# Max characters per command
echo "long args" | xargs -s 10 echo

COMMON PATTERNS#

# Delete found files
find . -name "*.tmp" -print0 | xargs -0 rm -f

# Grep in files
find . -name "*.py" | xargs grep "import"

# Count lines
find . -name "*.c" | xargs wc -l

# Change permissions
find . -type f | xargs chmod 644

# Copy files
find . -name "*.jpg" | xargs -I {} cp {} /backup/

# Move files
ls *.txt | xargs -I {} mv {} text_files/

# Create directories from file list
cat dirs.txt | xargs mkdir -p

# Download URLs
cat urls.txt | xargs -n 1 -P 5 wget

# Kill processes
pgrep pattern | xargs kill

# Tar multiple directories
echo "dir1 dir2 dir3" | xargs tar cvf archive.tar

HANDLING SPECIAL CHARACTERS#

# Spaces in filenames (IMPORTANT!)
# Wrong:
find . -name "*.txt" | xargs rm   # Breaks on spaces

# Correct:
find . -name "*.txt" -print0 | xargs -0 rm

# Or use -I (processes one at a time)
find . -name "*.txt" | xargs -I {} rm "{}"

# Quotes in filenames
find . -print0 | xargs -0 -I {} echo "'{}'"

COMBINING WITH OTHER TOOLS#

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

# With grep (better than find -exec)
find . -name "*.js" | xargs grep -l "TODO"

# With sed
find . -name "*.txt" | xargs sed -i 's/old/new/g'

# With awk
ps aux | awk '/python/ {print $2}' | xargs kill

# With cut
cat /etc/passwd | cut -d: -f1 | xargs -I {} id {}

# With ls
ls -1 *.jpg | xargs -I {} convert {} {}.png

REAL WORLD EXAMPLES#

# Batch image resize
find . -name "*.png" | xargs -P 4 -I {} convert {} -resize 800x600 resized/{}

# Bulk file rename
ls *.JPEG | xargs -I {} bash -c 'mv "$1" "${1%.JPEG}.jpg"' _ {}

# Search and replace in files
find . -name "*.py" -print0 | xargs -0 sed -i 's/old_func/new_func/g'

# Compress old logs
find /var/log -name "*.log" -mtime +7 | xargs -I {} gzip {}

# Git add specific files
git diff --name-only | xargs git add

# Install packages from list
cat packages.txt | xargs apt-get install -y

# Check disk usage of directories
find . -maxdepth 1 -type d | xargs du -sh

# Backup configuration files
find /etc -name "*.conf" | xargs -I {} cp {} /backup/

# Remove Docker images
docker images -q | xargs docker rmi

# Kill processes by name
ps aux | grep 'pattern' | awk '{print $2}' | xargs kill -9

XARGS VS FIND -EXEC#

# find -exec (one process per file)
find . -name "*.txt" -exec cat {} \;

# xargs (batches files, more efficient)
find . -name "*.txt" | xargs cat

# find -exec with + (similar to xargs)
find . -name "*.txt" -exec cat {} +

# When to use xargs:
# - More efficient for many files
# - Parallel execution (-P)
# - Complex argument manipulation
# - Input from sources other than find

# When to use -exec:
# - Simpler syntax
# - Works directly with find conditions
# - No pipe needed

DEBUGGING#

# Show what would run
echo "1 2 3" | xargs -t echo
# Output: echo 1 2 3
#         1 2 3

# Interactive confirmation
ls *.log | xargs -p rm
# rm file1.log file2.log?...y/n

# Verbose with -t
find . -name "*.tmp" | xargs -t rm

ERROR HANDLING#

# Exit on first error (default continues)
cat files.txt | xargs -I {} sh -c 'command {} || exit 255'

# Ignore errors
cat files.txt | xargs -I {} sh -c 'command {} || true'

QUICK REFERENCE#

xargs                   Execute with all input as args
xargs -n 1              One argument per execution
xargs -I {}             Replace {} with input
xargs -0                Null-delimited input
xargs -P N              N parallel processes
xargs -p                Prompt before execute
xargs -t                Print command (verbose)
xargs -r                Don't run if empty
xargs -d ':'            Custom delimiter