查找最新版本文件夹/文件并删除旧版本(无时间戳数据)
解决备份后多版本文件/文件夹的清理与重命名问题
核心思路
- 按基础名称分组:将带有
_00x后缀的文件/文件夹和无后缀的归为同一组(比如9、9_000、9_001属于9组;FILEA.TXT、FILEA_000.TXT属于FILEA.TXT组) - 按版本号排序:无后缀的视为初始版本,
_00x后缀的x值越大版本越新 - 筛选保留目标:每组内只保留最新的、有实际数据的条目(文件夹非空、文件大小>0),其余全部删除
- 重命名保留项:把保留的带后缀条目去掉后缀,恢复为原始名称
实用Bash脚本实现
下面是一个递归处理的脚本,支持多层目录(包括6层及以上):
#!/bin/bash # 递归处理目录 process_dir() { local dir="$1" # 遍历当前目录下的所有条目 for entry in "$dir"/*; do if [ -d "$entry" ]; then # 先递归处理子目录 process_dir "$entry" # 提取目录的基础名称(去掉_00x后缀) base_name=$(echo "$entry" | sed -E 's/_[0-9]{3}$//') # 收集同一组的所有目录 group_entries=("$base_name" "$base_name"_[0-9][0-9][0-9]) elif [ -f "$entry" ]; then # 提取文件的基础名称(去掉_00x后缀,保留扩展名) base_name=$(echo "$entry" | sed -E 's/_[0-9]{3}(\.[^.]+)$/\1/; s/_[0-9]{3}$//') # 收集同一组的所有文件 group_entries=("$base_name" "$base_name"_[0-9][0-9][0-9]*.* "$base_name"_[0-9][0-9][0-9]) else continue fi # 过滤存在的条目 existing_entries=() for ge in "${group_entries[@]}"; do if [ -e "$ge" ]; then existing_entries+=("$ge") fi done # 如果组内只有一个条目,跳过 if [ "${#existing_entries[@]}" -le 1 ]; then continue fi # 筛选有数据的条目:文件夹非空,文件大小>0 valid_entries=() for ee in "${existing_entries[@]}"; do if [ -d "$ee" ]; then # 判断文件夹是否为空(忽略隐藏文件的话去掉-A) if [ -n "$(ls -A "$ee")" ]; then valid_entries+=("$ee") fi elif [ -f "$ee" ]; then if [ "$(stat -c%s "$ee")" -gt 0 ]; then valid_entries+=("$ee") fi fi done # 确定要保留的条目:如果有有效条目,选版本号最大的;如果没有,全部删除(根据你的示例) if [ "${#valid_entries[@]}" -gt 0 ]; then # 按版本号排序,取最后一个(最新版本) sorted_valid=($(printf "%s\n" "${valid_entries[@]}" | sort -t '_' -k2,2n)) keep_entry="${sorted_valid[-1]}" else # 所有条目都为空,全部删除(比如你的示例中的9、9_000) keep_entry="" fi # 删除不需要的条目,重命名保留的条目 for ee in "${existing_entries[@]}"; do if [ "$ee" != "$keep_entry" ]; then echo "删除:$ee" rm -rf "$ee" elif [ -n "$keep_entry" ] && [[ "$keep_entry" != "$base_name" ]]; then echo "重命名:$keep_entry -> $base_name" mv "$keep_entry" "$base_name" fi done done } # 检查输入目录 if [ $# -ne 1 ]; then echo "用法:$0 <目标目录>" exit 1 fi target_dir="$1" if [ ! -d "$target_dir" ]; then echo "错误:目录 $target_dir 不存在!" exit 1 fi # 开始处理 echo "开始处理目录:$target_dir" process_dir "$target_dir" echo "处理完成!"
使用说明
- 测试先行:先复制一小部分测试数据到临时目录,运行脚本测试效果,确认符合预期后再处理真实数据
- 备份数据:在运行脚本前,务必备份好所有待处理的数据,避免误删
- 脚本调整:
- 如果需要忽略隐藏文件,修改文件夹非空判断的
ls -A为ls - 如果你的后缀不是3位数字(比如_0、_1),修改脚本中的
_[0-9]{3}为对应的正则(比如_[0-9]+)
- 如果需要忽略隐藏文件,修改文件夹非空判断的
- 权限问题:确保脚本有足够的权限读取、删除、重命名目标目录下的文件/文件夹
示例验证
针对你给出的示例:
- 文件夹组
9:删除9、9_000,保留并将9_001重命名为9 - 文件组
FILEA.TXT:删除FILEA.TXT、FILEA_000.TXT、FILEA_001.TXT,保留并将FILEA_002.TXT重命名为FILEA.TXT - 文件组
FILEB.TXT:删除FILEB.TXT,保留并将FILEB_000.TXT重命名为FILEB.TXT
完全匹配你的需求!
内容的提问来源于stack exchange,提问作者wade812
相关产品推荐
相关产品推荐

