← 中文资源

简体中文版本

Xargs 并行任务与分批控制

用 xargs 的 -P 与 -n 控制并行与分批:并发数封顶、批大小固定、keep-order 稳定输出、null 分隔路径含空格也安全。

阅读英文原文

示例说明

for 循环串行处理上千文件慢得难受,而 & 加 wait 的裸并发又失控。xargs -P 是标准答案:最大并发四、每批十个参数传给工作函数、输出按输入序稳定排列。print0 与 -0 的 null 分隔组合让含空格与换行的文件名万无一失——普通空格分隔在真实文件系统上是隐患。

技术要点

  • -P 封顶并发防资源失控
  • print0 加 -0 处理任意文件名
  • export -f 让子 shell 复用函数

代码解读

process_batch 按 xargs 传入的批次参数计数并逐文件取大小——stat 的两种形态兼容 Linux 与 BSD;export -f 导出函数供 bash -c 的子进程调用,_ 占位 $0。第二种形态用 -I{} 逐文件替换执行压缩。第三种演示 –no-run-if-empty:find 无结果时不触发命令,空输入是常态不是错误。

使用建议

工作函数要幂等且线程安全——并发下写同一输出文件会撕裂。CPU 密集任务并发数等于核数即可。GNU parallel 功能更强但依赖外装。

代码示例

#!/usr/bin/env bash
set -euo pipefail

readonly MAX_JOBS=4
readonly BATCH_SIZE=10

process_batch() {
  local batch_number=$1
  shift
  echo "batch ${batch_number}: 处理 $# 个文件"
  for file in "$@"; do
    local size
    size=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file")
    printf '%s\t%d bytes\n' "$(basename "$file")" "${size}"
  done
}
export -f process_batch

# -P 控制并发数,-N 每次传一批参数,--keep-order 稳定输出
find ./data -name '*.log' -type f -print0 \
  | xargs -0 -P "${MAX_JOBS}" -n "${BATCH_SIZE}" \
      bash -c 'process_batch "$@"' _ \
  | sort

# 不分批的高并发形态:一文件一任务
find ./data -name '*.small' -type f -print0 \
  | xargs -0 -P "${MAX_JOBS}" -I{} \
      sh -c 'gzip -k "{}" && echo "compressed {}"'

# 失败可见性:--no-run-if-empty 防空输入报错
find ./data -name '*.missing' -type f -print0 \
  | xargs -0 -r --no-run-if-empty echo "found"