核心是对比源文件与备份文件的last_write_time,源更新或备份不存在则触发备份;需用file_time_type转换比较,避免直接赋值或篡改时间戳导致误判。

如何用 std::filesystem::last_write_time 判断文件是否需要备份
核心逻辑很简单:对比源文件和目标备份目录中同名文件的最后修改时间,只要源文件更新(或目标不存在),就触发复制。但要注意,std::filesystem::last_write_time 返回的是 std::filesystem::file_time_type,不能直接用 比较不同文件系统的时钟(比如 NTFS 和 ext4 时间精度不同),也不能跨平台无脑转成 <code>time_t。
实操建议:
- 统一用
std::filesystem::file_time_type做比较,避免转换丢失精度或引发未定义行为 - 先检查目标路径是否存在(
std::filesystem::exists),再调用last_write_time,否则会抛std::filesystem::filesystem_error - Windows 下 FAT32 卷的修改时间精度只有 2 秒,NTFS 是 100ns;Linux ext4 通常是纳秒级——这意味着在 FAT32 上,两个间隔 1 秒内修改的文件可能被判定为“未变化”
遍历源目录时如何跳过符号链接和特殊文件
默认 std::filesystem::recursive_directory_iterator 会跟随符号链接,导致重复备份、循环遍历甚至崩溃。差异备份必须严格按物理路径处理,不能穿透链接。
实操建议:
- 构造迭代器时传入
std::filesystem::directory_options::skip_permission_denied和std::filesystem::directory_options::follow_directory_symlink的反向组合:显式禁用跟随,即不传follow_directory_symlink,并用std::filesystem::is_symlink(it->symlink_status())主动跳过 - 对每个
directory_entry先调用it->symlink_status()(不是status()),避免因权限或挂载点问题误抛异常 - 跳过设备文件、socket、FIFO 等非普通文件/目录:
!std::filesystem::is_regular_file(e) && !std::filesystem::is_directory(e)
复制文件前为什么要先写临时文件再原子替换
直接覆盖目标文件有风险:写入中途崩溃会导致备份损坏,且无法回滚。更糟的是,如果备份过程被中断,下次运行可能因时间戳混乱误判为“已备份”。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
实操建议:
- 生成临时文件名:在目标路径后加
.tmp_XXXXXX后缀(用std::tmpnam_s不安全,推荐用std::filesystem::temp_directory_path()+ 随机字符串) - 写完临时文件后,调用
std::filesystem::last_write_time(temp_path, std::filesystem::last_write_time(src_path))同步时间戳 - 最后用
std::filesystem::rename(temp_path, target_path)原子替换——该操作在同文件系统下是原子的,在跨文件系统时会退化为复制+删除,此时需额外检查返回值并清理临时文件
为什么不能只依赖修改时间做全量判断
修改时间可被任意篡改(touch -d "1970-01-01" file),且空文件或仅改变权限/所有者的文件不会更新 last_write_time。实际场景中,用户可能重命名、移动文件,或备份目录被手动清理过。
实操建议:
- 维护一个轻量元数据快照(如 JSON 文件),记录上次备份时每个文件的
last_write_time、大小、路径哈希(非内容哈希,用std::filesystem::file_size+ 路径即可) - 首次运行或快照丢失时,退化为全量扫描;后续运行优先查快照,再按时间戳二次确认
- 检测到目标目录中存在源目录没有的文件,不要自动删除——差异备份默认只增不删,除非明确启用
--prune模式
时间戳本身不是真相,只是线索。真正可靠的差异逻辑永远要结合上下文:你的备份策略是否允许删文件?是否接受秒级精度误差?是否要兼容 FAT32 设备?这些决定了你是否要在 last_write_time 外加一层校验。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










