You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

查找最新版本文件夹/文件并删除旧版本(无时间戳数据)

解决备份后多版本文件/文件夹的清理与重命名问题

核心思路

  • 按基础名称分组:将带有_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 "处理完成!"

使用说明

  1. 测试先行:先复制一小部分测试数据到临时目录,运行脚本测试效果,确认符合预期后再处理真实数据
  2. 备份数据:在运行脚本前,务必备份好所有待处理的数据,避免误删
  3. 脚本调整:
    • 如果需要忽略隐藏文件,修改文件夹非空判断的ls -A为ls
    • 如果你的后缀不是3位数字(比如_0、_1),修改脚本中的_[0-9]{3}为对应的正则(比如_[0-9]+)
  4. 权限问题:确保脚本有足够的权限读取、删除、重命名目标目录下的文件/文件夹

示例验证

针对你给出的示例:

  • 文件夹组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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:21:36