Multi-Tool Chains

find | xargs | awk — count lines per directory
# Count .adoc lines grouped by parent directory
find ~/atelier/_bibliotheca/domus-captures/docs/modules/ROOT/pages -name "*.adoc" -type f -print0 | \
  xargs -0 wc -l | awk '
    !/total$/ {
      dir = $2; sub(/\/[^/]+$/, "", dir)
      lines[dir] += $1
    }
    END {
      for (d in lines) printf "%6d %s\n", lines[d], d
    }
  ' | sort -rn | head -15
find | while read — safe per-file processing with spaces
# Process files one at a time — handles spaces and special chars
find ~/atelier/_bibliotheca/domus-captures/docs/modules/ROOT/pages -name "*.adoc" -type f -print0 | \
  while IFS= read -r -d '' file; do
    lines=$(wc -l < "$file")
    if (( lines > 100 )); then
      printf "%-6d %s\n" "$lines" "$file"
    fi
  done | sort -rn
find | parallel — GNU parallel integration
# Process 4 files simultaneously — useful for expensive operations
find ~/atelier/_bibliotheca/domus-captures/docs/modules/ROOT/pages -name "*.adoc" -type f -print0 | \
  parallel -0 -j4 'wc -l {} | awk "{printf \"%6d %s\\n\", \$1, \$2}"' | sort -rn | head -10

# Note: requires GNU parallel — install with: pacman -S parallel
-exec vs xargs — when to use each
# -exec: simpler, no pipe, handles filenames natively
find ~/atelier/_bibliotheca/domus-captures/docs -name "*.adoc" -type f \
  -exec grep -l ":description:" {} +

# xargs: when you need parallelism, batching, or multi-tool chains
find ~/atelier/_bibliotheca/domus-captures/docs -name "*.adoc" -type f -print0 | \
  xargs -0 -P4 grep -l ":description:"

# Rule: -exec for single commands, xargs for pipelines and parallelism
find | sort | head — largest/newest/oldest files
# Largest .adoc files
find ~/atelier/_bibliotheca/domus-captures/docs -name "*.adoc" -type f \
  -printf '%s\t%p\n' | sort -rn | head -10

# Most recently modified
find ~/atelier/_bibliotheca/domus-captures/docs -name "*.adoc" -type f \
  -printf '%T@\t%T+\t%p\n' | sort -rn | head -10 | cut -f2-

# Oldest files
find ~/atelier/_bibliotheca/domus-captures/docs -name "*.adoc" -type f \
  -printf '%T@\t%T+\t%p\n' | sort -n | head -10 | cut -f2-
find + process substitution — diff two directory trees
# Compare file lists between two directories without temp files
diff <(
  find ~/atelier/_bibliotheca/domus-captures/docs/modules/ROOT/pages -name "*.adoc" -type f \
    -printf '%f\n' | sort
) <(
  find ~/atelier/_bibliotheca/domus-captures/docs/modules/ROOT/partials -name "*.adoc" -type f \
    -printf '%f\n' | sort
) || true
find | tee — log what you find while processing
# Log every file found AND process it
find ~/atelier/_bibliotheca/domus-captures/docs -name "*.adoc" -type f -print0 | \
  tee >(tr '\0' '\n' > /tmp/find-audit-log.txt) | \
  xargs -0 wc -l | tail -1

# Check the log
echo "Files processed: $(wc -l < /tmp/find-audit-log.txt)"
head -5 /tmp/find-audit-log.txt
find feeding a for loop — with proper IFS handling
# WRONG — breaks on spaces in filenames:
# for f in $(find ... -print); do

# CORRECT — newline-safe with mapfile (bash 4+)
mapfile -d '' files < <(
  find ~/atelier/_bibliotheca/domus-captures/docs/modules/ROOT/pages/codex -name "*.adoc" -type f -print0
)

echo "Found ${#files[@]} codex pages"
for f in "${files[@]}"; do
  basename "$f"
done | sort | head -10