Linux Shell脚本优化:筛选指定前缀且日期为两天前及更早的文件并压缩
问题:基于文件名日期筛选并压缩指定文件
背景与需求
- 环境:Linux Shell
- 限制:无法通过文件创建日期筛选,只能借助文件名中的日期信息
- 现有文件列表:
- ABCADD01-20230801
- ABCADD01-20230802
- ABCADD01-20230803
- ABCADD01-20230804
- ABCADD02-20230801
- ABCADD02-20230802
- ABCAEE01-20230801
- ABCAEE01-20230802
- ABCAEE01-20230803
- ABCAFF01-20230801
- ABCAGG01-20230802
- 需求:筛选文件名包含
ABCADD、日期为两天前及更早(当前日期20230804)的文件并压缩,预期结果:- ABCADD01-20230801
- ABCADD01-20230802
- ABCADD02-20230801
- ABCADD02-20230802
原脚本问题分析
原脚本用双层for循环嵌套find,存在两个核心问题:
- 内层
find使用单引号包裹*$two_days_ago,单引号会阻止变量解析,实际匹配的是字面量*$two_days_ago而非计算后的日期值 - 逻辑错误:双层循环仅筛选了恰好等于两天前日期的文件,未覆盖更早的日期
原脚本代码:
# 获取两天前的日期 two_days_ago=$(date -d "2 days ago" +%Y%m%d) # 查找并压缩两天前修改的ABCADD文件 for file in $(find . -name 'ABCADD*' -type f ); do for file in $(find . -name '*$two_days_ago' -type f ); do echo "Zipping $file" gzip "$file" done done
优化实现方案
思路
- 提取每个
ABCADD文件名中的日期部分,转为可比较的整数 - 将文件日期与两天前的日期数值对比,筛选出小于等于该值的文件
- 避免冗余嵌套循环,直接遍历目标文件并逐一判断
当前目录筛选脚本(非递归)
# 计算两天前的日期(格式:YYYYMMDD) two_days_ago=$(date -d "2 days ago" +%Y%m%d) # 遍历当前目录下所有ABCADD开头的文件 for file in ABCADD*; do # 跳过非文件类型(如目录) [ -f "$file" ] || continue # 提取文件名中的日期部分(拆分最后一个'-'后的内容) file_date=${file##*-} # 比较日期数值:文件日期≤两天前日期则压缩 if [ "$file_date" -le "$two_days_ago" ]; then echo "Zipping $file" gzip "$file" fi done
递归筛选脚本(含子目录)
如果需要处理子目录中的文件,用find结合while read避免文件名含特殊字符的问题:
two_days_ago=$(date -d "2 days ago" +%Y%m%d) # 递归查找所有ABCADD开头的文件并逐个处理 find . -name 'ABCADD*' -type f | while read -r file; do file_date=${file##*-} if [ "$file_date" -le "$two_days_ago" ]; then echo "Zipping $file" gzip "$file" fi done
脚本说明
${file##*-}:Shell参数扩展语法,移除文件名中最后一个-及其之前的所有内容,直接提取日期段[ "$file_date" -le "$two_days_ago" ]:将日期作为整数比较,确保所有早于或等于两天前的文件都被选中
内容的提问来源于stack exchange,提问作者Chuuuuuu46
相关产品推荐
相关产品推荐

