Linux Basic — xargs & GNU Parallel

2 minute read

xargs & GNU Parallel

The fastest way to speed up a loop: run it in parallel. Both xargs and GNU parallel turn a list of inputs into concurrent command executions.


xargs Basics

xargs reads lines from stdin and passes them as arguments to a command:

ls *.txt | xargs rm
# equivalent to: rm file1.txt file2.txt file3.txt ...

Parallelise with xargs -P

# serial — one at a time
find . -name "*.jpg" | xargs -I {} convert {} {}.png

# parallel — 4 at a time
find . -name "*.jpg" | xargs -P 4 -I {} convert {} {}.png

-P N runs up to N commands concurrently.


xargs Quick Reference

Flag Meaning
-P N run N jobs in parallel
-I {} replace {} with each input line
-n N pass N args per invocation
-0 null-delimited input (pairs with find -print0)
-r don’t run if input is empty

Safe File Handling with -print0 / -0

Filenames with spaces or newlines break plain xargs:

# UNSAFE
find . -name "*.log" | xargs rm

# SAFE
find . -name "*.log" -print0 | xargs -0 rm

-print0 separates with \0 (null byte), which no filename can contain.


GNU Parallel

GNU Parallel is xargs on steroids — better syntax, progress bars, retry logic, and remote execution.

Install

# macOS
brew install parallel

# Ubuntu/Debian
apt install parallel

Basic Usage

# convert images in parallel
find . -name "*.jpg" | parallel convert {} {.}.png

# {.} is the basename without extension

Parallel with function

process() {
    echo "processing $1"
    sleep 1
}
export -f process

find . -name "*.txt" | parallel process

Parallel Options

Flag Meaning
-j N run N jobs (default: num cores)
--bar show progress bar
--eta estimate time remaining
--dry-run print commands without running
--retry-failed re-run failed jobs
parallel -j 8 --bar process ::: file1 file2 file3 file4

When Parallelism Helps

Workload Parallelism Gain
CPU-bound (compression, encoding) ~linear with cores
I/O-bound (network requests, file reads) high (limited by I/O, not CPU)
Serial dependencies none — can’t parallelise

If each job is < 0.1 seconds, the fork overhead may exceed the gain.


Benchmark: Serial vs Parallel

# serial (100 files × 1s each = 100s)
time for f in *.jpg; do convert "$f" "${f%.jpg}.png"; done

# parallel -j 8 (100 / 8 ≈ 12.5s + overhead ≈ 15s)
time find . -name "*.jpg" | parallel -j 8 convert {} {.}.png

6–8× speedup on an 8-core machine.


Caveat: Resource Limits

Running 100 jobs in parallel can exhaust:

  • File descriptors
  • Memory (if each job uses 500MB)
  • Network connections

Start with -P = num cores, then tune.


Next → Practice Exercises

Updated: