在Bash中批量处理文件并实时更新进度条的实现方案
自定义流式文件处理脚本(满足实时状态、错误捕获、可选并行有序输出)
单进程流式实现(满足核心需求)
直接通过Bash循环流式处理文件,无需等待全量列表加载,同时实现自定义彩色状态行、错误捕获:
#!/bin/bash set -uo pipefail # 定义彩色输出常量 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' NC='\033[0m' # 重置颜色 # 初始化计数器与错误记录 current_idx=0 received_total=0 declare -a error_status=() # 退出时清理终端状态 cleanup() { echo -ne "\033[K\033[0m\n" >&2 } trap cleanup EXIT # 流式读取并处理文件 while IFS= read -r file; do ((received_total++)) ((current_idx++)) # 打印实时处理状态(覆盖当前行) echo -ne "\033[1G\033[K" >&2 echo -ne "${YELLOW}处理中: 第 ${current_idx}/${received_total} 个 | 文件: ${GREEN}${file}${NC}" >&2 # 执行处理命令,保留其stderr输出,捕获错误码 if your_process_command "$file"; then error_status[$current_idx]="${GREEN}成功${NC}" else err_code=$? error_status[$current_idx]="${RED}失败(码: ${err_code})${NC}" # 可选:将错误信息写入日志 echo "文件 ${file} 处理失败,错误码: ${err_code}" >> process_errors.log fi # 更新状态行标记处理结果 echo -ne "\033[1G\033[K" >&2 echo -ne "${YELLOW}已完成: 第 ${current_idx}/${received_total} 个 | 文件: ${GREEN}${file}${NC} | 状态: ${error_status[$current_idx]}" >&2 done # 输出最终统计 echo -ne "\033[K\033[0m\n" >&2 echo "=== 处理完成 ===" >&2 failed_count=$(printf "%s\n" "${error_status[@]}" | grep -c "失败") echo "总文件数: ${received_total} | 成功: $((received_total - failed_count)) | 失败: ${failed_count}" >&2
关键细节说明
set -uo pipefail:增强错误检测,避免管道环节的错误被忽略IFS= read -r file:正确处理含空格、特殊字符的文件名echo -ne:结合ANSI转义序列(\033[1G回到行首、\033[K清除当前行)实现状态行实时覆盖- 处理命令的
stderr会直接输出到终端,不会被状态行干扰 - 错误码捕获后可自定义日志记录逻辑
并行有序实现(可选需求)
基于GNU Parallel实现多进程并行,通过--keep-order保证输出有序,同时自定义状态行(替代默认--bar):
#!/bin/bash set -uo pipefail RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' NC='\033[0m' # 临时文件跟踪进度,退出时自动清理 progress_file=$(mktemp) trap 'rm -f "$progress_file"' EXIT echo "0 0" > "$progress_file" # 后台进程:实时更新状态行 update_status() { while true; do read -r done total < "$progress_file" if [[ $total -eq 0 ]]; then status="${YELLOW}等待文件输入...${NC}" else status="${YELLOW}处理进度: ${done}/${total} 个文件${NC}" fi echo -ne "\033[1G\033[K${status}" >&2 sleep 0.5 # 进度完成时退出后台进程 [[ $done -eq $total && $total -ne 0 ]] && break done } update_status & status_pid=$! # Parallel并行处理:--keep-order保证输出有序,--jobs设置并行数 parallel --keep-order --joblog "$progress_file" --jobs 4 \ 'your_process_command {}; echo "$(($(awk '\''{print $1}'\'' '"$progress_file"') + 1)) $(awk '\''{print $2}'\'' '"$progress_file"')" > "$progress_file"' # 等待状态更新进程结束 wait $status_pid # 统计处理结果 total=$(awk '{print $2}' "$progress_file") failed=$(awk '$7 != 0' "$progress_file" | wc -l) echo -ne "\033[K\033[0m\n" >&2 echo "=== 并行处理完成 ===" >&2 echo "总文件数: ${total} | 成功: $((total - failed)) | 失败: ${failed}" >&2
关键细节说明
--keep-order:确保单个文件的输出完整后再显示下一个,满足有序需求--joblog:自动记录总任务数与已完成任务数,用于状态行更新- 后台进程定期读取进度文件,实现实时状态更新
--jobs 4:可根据CPU核心数调整并行进程数
内容的提问来源于stack exchange,提问作者localhost
相关产品推荐
相关产品推荐

