Java的Files.move()默认不保留所有属性,需显式传入StandardCopyOption.COPY_ATTRIBUTES才能尽可能复制时间戳、权限、所有者等;跨文件系统时行为受限于目标系统能力,creationTime在Linux无原生支持,必要时可手动逐项设置属性。

Java 的 Files.move() 方法本身支持在重命名文件时保留原始属性,但**默认不保留所有属性**,需显式指定 StandardCopyOption.COPY_ATTRIBUTES 选项。
关键前提:使用 COPY_ATTRIBUTES 选项
仅调用 Files.move(source, target) 不会保留创建时间(creationTime)、最后访问时间(lastAccessTime)、文件权限、所有者等属性。必须传入 COPY_ATTRIBUTES:
Files.move(source, target, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES)-
COPY_ATTRIBUTES尽可能复制源文件的属性,包括:最后修改时间(lastModifiedTime)、最后访问时间(lastAccessTime)、创建时间(creationTime)(Windows 支持,Linux/macOS 通常忽略)、文件权限(POSIX 或 DOS 属性)、所有者与组信息(取决于操作系统和 JVM 权限)
注意跨文件系统行为
如果源路径和目标路径位于不同文件系统(例如从 /home 移动到 /mnt/usb),move() 实际执行的是“复制 + 删除”。此时 COPY_ATTRIBUTES 仍生效,但部分属性可能受限于目标文件系统能力:
- NTFS → NTFS:完整支持 creationTime、DOS 属性等
- ext4 → ext4:支持 POSIX 权限、所有者、时间戳;creationTime 在 Linux 上无原生概念,JVM 可能映射为 birthTime(需 Java 11+ 且文件系统支持)
- FAT32 / exFAT:不支持 Unix 权限或纳秒精度时间戳,部分属性会被忽略或降级
验证属性是否成功保留
移动后建议主动检查关键属性,尤其是对时间敏感的场景:
- 读取源文件属性:
Files.readAttributes(source, BasicFileAttributes.class) - 读取目标文件属性:
Files.readAttributes(target, BasicFileAttributes.class) - 对比
lastModifiedTime()、lastAccessTime()、creationTime()是否一致 - 检查权限:
Files.getPosixFilePermissions(target)(POSIX 系统)或Files.getAttribute(target, "dos:readonly")(Windows)
替代方案:手动复制属性(更可控)
若 COPY_ATTRIBUTES 在特定环境失效(如容器中权限受限),可先移动再手动设置:
- 用
Files.move(..., REPLACE_EXISTING)完成重命名 - 读取源文件的
BasicFileAttributes和PosixFileAttributes(或DosFileAttributes) - 用
Files.setLastModifiedTime(target, attr.lastModifiedTime())、Files.setPosixFilePermissions(target, perms)等逐项设置 - 注意:creationTime 无法通过标准 API 设置(Java 不提供
setCreationTime()),需依赖平台特定方式(如 JNA 调用 native API)










