示例说明
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"