Stage 3 · Build
Shell Scripting & Automation
find, xargs & Parallelism
find predicates, null-delimited paths, xargs -P, and avoiding unsafe filename handling.
find Predicates
# Find by name
find /var/log -name "*.log"
find / -type f -name "nginx.conf"
# Find by type
find / -type f # Files only
find / -type d # Directories only
find / -type l # Symlinks only
# Find by size
find / -size +100M # Larger than 100MB
find / -size -1k # Smaller than 1KB
# Find by time
find /var/log -mtime -1 # Modified in last 24 hours
find / -mmin -30 # Modified in last 30 minutes
find / -atime +30 # Not accessed in 30 days
find / -ctime -7 # Changed in last 7 days
# Find by permission
find / -perm 777 # Exact permission match
find / -perm -u+s # Setuid files
find / -perm /o+w # World-writable files
# Find by owner
find / -user root
find / -nouser # Orphaned files
# Combine predicates
find / -type f -size +100M -mtime -7 -user rootfind is the most flexible file search tool. Combine predicates with -and (default), -or, and -not for complex searches.
xargs Basics
# Basic xargs: read from stdin, execute command
echo "file1 file2 file3" | xargs rm
find /tmp -name "*.tmp" | xargs rm
# Limit arguments per command
find /var/log -name "*.log" | xargs -n 1 ls -la
# Custom delimiter
echo "one:two:three" | xargs -d: echo
# Show command before executing
find /tmp -name "*.tmp" | xargs -t rm
# Handle empty input
echo "" | xargs -r rm # -r: don't run if input is empty
# Interactive mode (ask before each command)
find /tmp -name "*.tmp" | xargs -p rmxargs converts stdin into command arguments. -n limits arguments per invocation, -r prevents empty command execution.
Null-Delimited Paths
# DANGEROUS: filenames with spaces break xargs
find . -name "*.txt" | xargs rm # BREAKS on "file with spaces.txt"
# SAFE: null-delimited output
find . -name "*.txt" -print0 | xargs -0 rm
# -print0 outputs null-delimited filenames
# -0 reads null-delimited input
# Real-world examples
find / -type f -size +100M -print0 | xargs -0 du -sh
find . -name "*.log" -print0 | xargs -0 grep -l "error"
# With GNU find, use -print0 for any user-provided paths
find "$DIR" -print0 | xargs -0 -I{} command {}Always use -print0 and -0 for filenames that may contain spaces, newlines, or special characters. This prevents injection attacks.
xargs Parallelism
# Run 4 parallel jobs
find /var/log -name "*.gz" | xargs -P 4 -I{} gunzip {}
# Parallel compression
find . -type f -name "*.txt" -print0 | xargs -0 -P 8 -I{} gzip {}
# Parallel SSH
cat hosts.txt | xargs -P 10 -I{} ssh {} uptime
# Count available CPUs
NPROC=$(nproc)
find /data -name "*.csv" -print0 | xargs -0 -P $NPROC -I{} process_csv {}
# Monitor parallel jobs
find /data -name "*.csv" -print0 | \
xargs -0 -P 8 -I{} bash -c 'echo "Processing {}"; process_csv {}; echo "Done {}"'-P N limits parallel jobs to N. Use nproc to get CPU count. -I{} replaces {} with each input line.
Unsafe Filename Handling
# DANGEROUS: filenames starting with -
find . -name "*.log" | xargs rm
# If a file is named "-rf /", this executes: rm -rf /
# SAFE: use -- to terminate options
find . -name "*.log" -print0 | xargs -0 rm --
# DANGEROUS: filenames with newlines
echo "file1
file2" | xargs rm # Treats as one filename
# SAFE: null-delimited
printf "file1\0file2\0" | xargs -0 rm
# DANGEROUS: command injection via filenames
echo 'malicious filename; rm -rf /' | xargs
# SAFE: null-delimited and -0
find . -print0 | xargs -0 -I{} command -- "{}"
# Check for dangerous filenames
find . -print0 | xargs -0 -I{} bash -c 'echo "{}" | grep -q "^-" && echo "DANGER: {}"Filenames can contain any character except / and null. Always use -print0/-0 and -- to prevent injection and argument parsing issues.
GNU Parallel
# Install parallel
sudo apt install parallel
# Basic parallel execution
cat hosts.txt | parallel ssh {} uptime
# Parallel with output control
cat hosts.txt | parallel --joblog joblog.txt ssh {} uptime
# Limit parallel jobs
parallel -j 4 gzip ::: *.txt
# Use {} as placeholder
find . -name "*.txt" | parallel gzip {}
# Preserve order
find . -name "*.txt" | parallel -k gzip {}
# Show progress
find . -name "*.txt" | parallel --progress gzip {}GNU parallel is more powerful than xargs -P. It handles job logging, output control, and better error handling.
Filenames can contain spaces, newlines, and special characters. Use find -print0 | xargs -0 to handle them safely.
Files named -rf, -f, or similar can cause command injection. Always use -- to terminate find/xargs options.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.