filepath.Walk可安全遍历备份目录:需检查info.IsDir()跳过目录、用strings.HasSuffix或正则匹配备份文件名、调用info.ModTime()获取时间戳;按保留策略分组筛选后,配合-dry-run模式与日志输出再执行os.Remove。

如何用 filepath.Walk 安全遍历备份目录
直接用 os.RemoveAll 或通配符 rm -rf 清理备份目录极容易误删正在使用的文件,必须先识别“冗余”——即过期、重复或非保留策略内的文件。Go 标准库的 filepath.Walk 是最稳妥的起点,它按深度优先遍历,支持错误中断,且不依赖 shell 工具。
注意三点:
• 遍历时务必检查 info.IsDir(),跳过目录本身,只处理文件;
• 用 strings.HasSuffix 或正则匹配备份文件名(如 backup_20240501T123000.tar.gz),避免匹配到日志或临时文件;
• 对每个文件调用 info.ModTime() 而非 info.Sys().(*syscall.Stat_t).Ctim —— 后者在不同 OS 上行为不一致,且 Go 1.19+ 已弃用。
按保留策略筛选需删除的文件:保留最近 N 个 + 按时间间隔归档
单纯留“最近 7 个”不够,生产环境常需混合策略:比如保留最近 7 天每日一个,再保留每周第一个、每月第一个。这需要对文件按时间戳分组,而非简单排序后切片。
实操建议:
• 提取文件名中的时间戳(推荐用 time.Parse 解析 ISO8601 或自定义格式),失败则跳过该文件;
• 将所有有效文件按 time.Time 排序(降序),再用 map 分组:键为 year-month、year-week 等;
• 对每组只保留首个(最新),其余标记为待删;
• 特别注意时区:统一用 time.UTC 解析和比较,避免本地时区导致跨日误判。
立即学习“go语言免费学习笔记(深入)”;
批量删除前务必启用 dry-run 模式与日志输出
线上脚本一旦误删不可逆,os.Remove 不会二次确认。必须默认开启 dry-run,并通过 flag 控制真实执行。
关键实现:
• 命令行加 -dry-run flag(用 flag.Bool),默认为 true;
• 删除逻辑封装成函数,接收 dryRun bool 参数,仅当 !dryRun 时调用 os.Remove;
• 所有将删的文件路径必须写入日志(用 log.Printf),格式为 "would remove: %s (modtime: %v)";
• 错误不 panic,而是记录 log.Printf("failed to remove %s: %v", path, err) 并继续下一个。
为什么不用 exec.Command("find", ...) 调用 shell?
看似省事,但隐患多:路径含空格或特殊字符时易被 shell 截断;不同系统 find -mtime 行为不一致(macOS 的 find 不支持 -printf);权限问题导致子进程无法读取某些目录,而 Go 自身可捕获并跳过。
更实际的问题:
• exec.Command 启动新进程开销大,千级文件下比纯 Go 遍历慢 3–5 倍;
• 无法精确控制时间判断逻辑(比如按周/月归档);
• 日志和错误难以与主程序上下文关联,调试困难;
• 容器环境中可能根本没装 find 或版本过旧。
真正复杂的点不在遍历或删除,而在时间分组策略的边界 case:比如某月最后一天的备份,是否算作下月归档?这类逻辑必须显式编码,没法靠 shell 命令糊弄过去。


















