如何用Bash Shell实现日志筛选、文件迁移及清理的自动化流程?
完善Bash脚本实现日志处理与文件自动化流转流程
完整脚本实现
#!/bin/bash # 定义核心文件路径 TARGET_LOG="convert.20231010.log" CATEGORY2_PATH="./category2" CATEGORY3_PATH="./category3" # 生成带时间戳的操作日志 OPERATION_LOG="operation_$(date +%Y%m%d_%H%M%S).log" # 确保输出同时写入操作日志和终端 exec > >(tee -a "$OPERATION_LOG") 2>&1 echo "=== 操作开始于 $(date) ===" # 步骤a:筛选目标日志行并提取路径/文件名 # 假设日志格式示例:"2023-10-10 14:30:00 Fail: /data/xxx/file.txt is not found" # 若日志格式不同,需调整awk字段定位($NF为最后一个字段,此处根据实际情况修改) echo "1. 筛选并提取日志中符合条件的文件信息..." FAILED_FILES=$(grep -E 'Fail.*is not found' "$TARGET_LOG" | awk '{print $3}') if [ -z "$FAILED_FILES" ]; then echo "未找到符合条件的日志行,操作结束" exit 0 fi # 循环处理每个提取到的文件 for FILE_PATH in $FAILED_FILES; do FILE_NAME=$(basename "$FILE_PATH") SOURCE_FILE="$CATEGORY2_PATH/$FILE_NAME" DEST_FILE="$CATEGORY3_PATH/$FILE_NAME" echo "--- 处理文件: $FILE_NAME ---" # 步骤b:检查category2中是否存在目标文件 if [ ! -f "$SOURCE_FILE" ]; then echo "警告:$SOURCE_FILE 不存在,跳过此文件" continue fi # 步骤c:检查CARD字段是否非空 # 假设CARD字段格式为"CARD=123456",若格式不同需调整匹配规则 if grep -q '^CARD=[^[:space:]]' "$SOURCE_FILE"; then echo "CARD字段非空,移动文件至$CATEGORY3_PATH" mv "$SOURCE_FILE" "$DEST_FILE" if [ $? -eq 0 ]; then echo "文件移动成功" else echo "错误:文件移动失败" fi else echo "CARD字段为空,不移动文件" fi # 步骤d:标记待删除的日志行(最后统一删除,避免循环中修改日志导致的问题) # 先收集所有待删除行的匹配串,最后一次性处理 DELETE_PATTERNS+=("$(echo "$FILE_PATH" | sed 's/\//\\\//g')") done # 统一删除日志中符合条件的行,并备份原日志 echo "2. 删除日志中符合条件的行..." DELETE_REGEX=$(IFS='|'; echo "${DELETE_PATTERNS[*]}") sed -i.bak "/Fail.*($DELETE_REGEX).*is not found/d" "$TARGET_LOG" echo "已删除符合条件的日志行,原日志备份为 ${TARGET_LOG}.bak" echo "=== 操作结束于 $(date) ==="
关键环节说明
- 日志筛选与提取:用
grep -E匹配同时包含"Fail"和"is not found"的行,通过awk提取文件路径。如果你的日志格式和示例不同,需要调整awk的字段索引(比如把$3改成对应路径所在的字段位置)。 - 文件路径处理:用
basename提取纯文件名,避免路径层级影响category2的文件查找。 - CARD字段检查:
grep -q '^CARD=[^[:space:]]'匹配以"CARD="开头且后面非空的行,确保字段有有效值。如果你的CARD字段格式不同(比如没有等号、位置不同),需要修改正则表达式。 - 日志行删除:先收集所有待处理的文件路径,最后用
sed一次性删除匹配行,避免循环中修改日志文件导致的读取异常,同时用-i.bak备份原日志,防止误操作。 - 操作日志记录:通过
exec > >(tee -a "$OPERATION_LOG") 2>&1将所有终端输出同时写入操作日志,方便后续排查。
注意事项
- 确保脚本执行前,
category2和category3目录已存在,可添加mkdir -p "$CATEGORY2_PATH" "$CATEGORY3_PATH"到脚本开头避免报错。 - 测试脚本时,建议先复制一份日志文件进行测试,避免误修改原始日志。
- 若日志中包含特殊字符(如空格、括号),需要修改
FAILED_FILES的处理方式,改用while read循环读取,避免字段拆分错误:grep -E 'Fail.*is not found' "$TARGET_LOG" | awk '{print $3}' | while read -r FILE_PATH; do # 循环内容不变 done
内容的提问来源于stack exchange,提问作者Headshot
相关产品推荐
相关产品推荐

