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