shutil.copy()仅复制文件内容和部分权限,不保留修改时间等元数据;shutil.copy2()通过copystat()补全元数据,适用于备份等时间敏感场景。

shutil.copy() 和 shutil.copy2() 差在哪?
只复制文件内容,用 shutil.copy();要连修改时间、权限等元数据一起拷过去,必须用 shutil.copy2()。很多人以为 copy() 也能保留时间戳,结果部署后脚本因 mtime 判断失效——这就是没看清文档里那句 “copy2() preserves more metadata”。
-
shutil.copy(src, dst):只保证文件内容和部分权限(如可执行位),不保留st_mtime、st_atime -
shutil.copy2(src, dst):调用copystat()补全元数据,适合备份、同步等对时间敏感的场景 - Windows 下两者都可能无法完全保留所有 NTFS 属性(比如 ACL),别依赖它做权限审计
复制整个文件夹该用 shutil.copytree() 还是自己遍历?
直接上 shutil.copytree(),除非你要跳过某些子目录、重命名文件或做内容过滤。它的默认行为是递归创建目标路径、逐文件调用 copy2(),比手写 os.walk() + shutil.copy2() 稳定得多。
- 目标目录不能已存在,否则抛
FileExistsError;加dirs_exist_ok=True(Python 3.8+)可覆盖已有目录 - 想忽略某些文件?传
ignore=shutil.ignore_patterns('*.tmp', '__pycache__') - 旧版本 Python(shutil.rmtree(dst) 再 copytree,但要注意权限问题(比如只读文件)
shutil.copyfile() 报错 “Same file” 怎么回事?
这个错误不是路径写错了,而是源和目标指向了同一个 inode —— 常见于符号链接没解引用、或者用了相对路径导致实际解析后相同。比如 shutil.copyfile('a.txt', './a.txt') 在当前目录下就会触发。
- 检查是否用了软链:
os.path.samefile(src, dst)可提前判断(返回 True 就别 copy) - 避免相对路径歧义:统一用
os.path.abspath()规范路径再比较 -
shutil.copyfile()不支持目录,也不复制元数据,纯内容搬运;误用它处理带权限/时间的配置文件,后续 diff 会发现时间戳全变成当前时间
跨文件系统移动大文件,用 shutil.move() 安全吗?
不安全。如果源和目标在不同磁盘(比如 /home → /mnt/backup),shutil.move() 实际是先 copy2() 再 os.unlink(),中间出错(磁盘满、断电)会导致文件丢失或只剩半截。
立即学习“Python免费学习笔记(深入)”;
- 生产环境批量迁移,优先用系统命令:
subprocess.run(['rsync', '-a', src, dst]),支持断点续传和校验 - 非得用 shutil?加 try/except + 校验步骤:复制后
filecmp.cmp(src, dst, shallow=False),确认一致再删源 -
shutil.move()在同分区下才是原子 rename,这点常被忽略——日志轮转、临时文件切换时若跨分区,就失去原子性保障










