xargs Command in Linux — Build and Execute Commands
xargs reads items from standard input (or a file) and executes a command with those items as arguments. It bridges the gap between commands that output lists and commands that need arguments — a critical tool for batch processing and automation.
What You’ll Learn
By the end of this tutorial, you’ll know how to use xargs for basic argument building, control delimiters, use placeholders, limit arguments per command, run tasks in parallel, handle null-separated input from find, simulate commands with dry-run, and handle special characters safely.
Why xargs Matters
Many Linux commands output lists (find, grep -l, ls), but few accept input via pipe directly. xargs converts that output into command-line arguments. Durga Antivirus Pro uses xargs to batch-scan files found by find, and DodaZIP uses it to compress files in parallel across multiple CPU cores.
xargs Learning Path
flowchart LR
A[find Command] --> B[xargs Command<br/>You are here]
B --> C[Shell Scripting]
C --> D[Process Management]
D --> E[Automation]
style B fill:#f90,color:#fff
Syntax Overview
command | xargs [options] [command [initial-arguments]]| Option | Description |
|---|---|
-n N | Max number of arguments per command |
-I placeholder | Replace string in command with input |
-P N | Run up to N processes in parallel |
-d delim | Use custom delimiter (not whitespace) |
-0 | Null-delimited input (with find -print0) |
-t | Print command before executing (trace) |
-p | Prompt before executing each command |
-r | Don’t run if input is empty (GNU default) |
10 Practical Examples
1. Basic xargs — Convert Input to Arguments
Remove all .tmp files listed by find:
echo "file1.tmp file2.tmp file3.tmp" | xargs rmNo output if successful. Check:
echo "file1.tmp file2.tmp file3.tmp" | xargs ls -la 2>&1 | head -3ls: cannot access 'file1.tmp': No such file or directory
ls: cannot access 'file2.tmp': No such file or directory2. Custom Delimiter
Process a comma-separated list:
echo "apple,banana,cherry,date" | xargs -d ',' -n 1 echo "Fruit:"Fruit: apple
Fruit: banana
Fruit: cherry
Fruit: date3. Placeholder with -I
Use {} as a placeholder for where the input appears in the command:
echo "data.txt" | xargs -I {} cp {} /backup/{}.bakThis copies data.txt to /backup/data.txt.bak.
Move files into a directory:
echo "file1 file2" | xargs -I {} mv {} /target/dir/4. Limit Arguments per Command (-n)
wc -l on each file individually:
echo -e "file1.txt\nfile2.txt\nfile3.txt" | xargs -n 1 wc -lIf file1.txt has 5 lines, file2.txt has 3, file3.txt has 8:
5 file1.txt
3 file2.txt
8 file3.txtWithout -n, xargs passes all files at once:
echo -e "file1.txt\nfile2.txt\nfile3.txt" | xargs wc -l5 file1.txt
3 file2.txt
8 file3.txt
16 total5. Parallel Execution (-P)
Compress all .log files in parallel (4 at a time):
find /var/log -name "*.log" -type f | xargs -P 4 -I {} gzip {}No direct output, but processes run simultaneously. Verify:
ls /var/log/*.log.gz 2>/dev/null | head -3/var/log/syslog.gz
/var/log/kern.log.gz
/var/log/auth.log.gz6. Null Delimiter with find
Safe handling of filenames with spaces:
find /home -name "*.bak" -type f -print0 | xargs -0 rmThe -print0 flag uses null characters (not newlines) to separate filenames. -0 tells xargs to expect null-delimited input. This is essential when filenames contain spaces, tabs, or newlines.
7. Combining with find
Find all Python files and count lines:
find /home/projects -name "*.py" -type f | xargs wc -l 125 /home/projects/src/main.py
42 /home/projects/src/utils.py
15 /home/projects/tests/test_main.py
182 totalFind files containing “TODO” and edit them:
grep -rl "TODO" /home/projects/ | xargs sed -i 's/TODO/FIXME/g'8. Dry Run / Trace Mode
Print each command before executing:
echo "file1 file2 file3" | xargs -t rmrm file1 file2 file3The -t flag shows what command will run before executing it. Use this for safety when testing.
9. Interactive Prompt
Prompt before each execution:
find /tmp -name "*.tmp" | xargs -p rmrm /tmp/abc.tmp /tmp/xyz.tmp ?...y10. Handle Special Characters
Filenames with spaces require special handling:
# Dangerous: will fail on "My File.txt"
find /home -name "*.txt" | xargs rm
# Safe: handles spaces correctly
find /home -name "*.txt" -print0 | xargs -0 rmCommon Use Cases
Delete Files Older Than 30 Days
find /var/log -name "*.log" -mtime +30 -print0 | xargs -0 rmChange File Extensions
find . -name "*.html" -print0 | xargs -0 -I {} mv {} {}.bakCount Lines in All Source Files
find . \( -name "*.py" -o -name "*.js" \) -print0 | xargs -0 wc -lParallel Compression
find /var/log -name "*.log" -mtime +1 -print0 | xargs -0 -P $(nproc) gzipCommon Mistakes
1. Not Using -0 with find -print0
If filenames contain spaces, tabs, or newlines, xargs splits them incorrectly. Always pair find -print0 with xargs -0.
2. Forgetting That xargs Appends Arguments by Default
xargs cmd runs cmd input1 input2 .... Use -I to place input at a specific position in the command.
3. Running Dangerous Commands Without Testing
find . -name "*.log" | xargs rm could delete files you didn’t intend. Use -p or -t first to verify.
4. Command-Line Length Limits
Without -n, xargs packs as many arguments as possible into one command. Very large lists may exceed the system’s maximum argument length. Use -n 100 to limit batch size.
Practice Questions
1. How do you safely pass filenames with spaces from find to xargs?
Use find ... -print0 | xargs -0 command
2. What does -n 1 do in xargs?
It limits each invocation of the command to exactly 1 argument from input.
3. How do you use xargs to run commands in parallel?
Use -P N where N is the number of parallel processes. Example: xargs -P 4 -I {} cmd {}
4. What’s the difference between xargs -t and xargs -p?
-t prints each command before executing (no confirmation). -p prints and asks for confirmation before each execution.
5. Challenge: Write a one-liner using find and xargs that finds all .log files, compresses them with gzip, using 4 parallel processes, safely handling filenames.
find /var/log -name "*.log" -type f -print0 | xargs -0 -P 4 -I {} gzip {}
Mini Project: Batch File Processor
#!/bin/bash
# batch_process.sh — Process files matching criteria
# Usage: ./batch_process.sh /path/to/scan
SCAN_DIR="${1:?Usage: $0 /path/to/scan}"
ACTION="${2:-count}" # count, compress, backup
case "$ACTION" in
count)
echo "Counting lines in source files..."
find "$SCAN_DIR" \( -name "*.py" -o -name "*.js" -o -name "*.sh" \) \
-type f -print0 | xargs -0 wc -l
;;
compress)
echo "Compressing large files (>10MB)..."
find "$SCAN_DIR" -type f -size +10M -print0 | \
xargs -0 -P "$(nproc)" -I {} gzip -v {} 2>/dev/null
echo "Done."
;;
backup)
BACKUP_DIR="/tmp/backup-$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
find "$SCAN_DIR" -type f -mtime -1 -print0 | \
xargs -0 -I {} cp {} "$BACKUP_DIR"
echo "Backed up to: $BACKUP_DIR"
echo "Files: $(ls "$BACKUP_DIR" | wc -l)"
;;
esacExpected output (count action):
Counting lines in source files...
125 /home/projects/src/main.py
42 /home/projects/src/utils.py
15 /home/projects/tests/test_main.py
30 /home/projects/scripts/deploy.sh
212 totalFAQ
What’s Next
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro