Windows使用shutil.move跨磁盘移动文件报错WinError 17怎么解决?
问题解决方案
报错原因
WinError 17 跨磁盘移动失败的核心触发点有3个:
- 你当前使用的
on_modified事件会在目录发生任何改动时反复触发,移动文件的操作本身会修改原监听目录,导致回调重复执行,出现文件被占用、重复移动的冲突 - 硬编码拼接路径的方式在Windows环境下容易出现路径格式不兼容,
shutil.move无法正确识别跨盘路径 - 未判断文件状态就直接执行移动,可能触发未完全下载/被其他程序占用的文件的移动操作
修复步骤
- 补全缺失的依赖导入,你的原代码未导入
os、Observer、FileSystemEventHandler相关模块 - 使用
os.path.join拼接路径,适配Windows系统的路径规则 - 增加文件状态判断、重复触发拦截逻辑,避免重复执行移动操作
- 增加目标路径存在校验,避免同名文件冲突
修复后完整代码
import os import shutil import time from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler # 增加全局锁避免重复触发回调 is_moving = False folder_to_track = '/Users/sia/Downloads/Telegram Desktop' folder_destination = 'D:/test_folder' # 先确保目标文件夹存在 os.makedirs(folder_destination, exist_ok=True) class MyHandler(FileSystemEventHandler): def on_modified(self, event): global is_moving if is_moving: return is_moving = True try: # 等待1秒避免文件还在写入中就被移动 time.sleep(1) for filename in os.listdir(folder_to_track): src = os.path.join(folder_to_track, filename) # 跳过文件夹,只处理文件 if not os.path.isfile(src): continue new_destination = os.path.join(folder_destination, filename) # 处理同名文件,自动加后缀 counter = 1 while os.path.exists(new_destination): name, ext = os.path.splitext(filename) new_destination = os.path.join(folder_destination, f"{name}_{counter}{ext}") counter += 1 shutil.move(src, new_destination) finally: is_moving = False event_handler = MyHandler() observer = Observer() observer.schedule(event_handler, folder_to_track, recursive=True) observer.start() # 保持程序运行 try: while True: time.sleep(1) except KeyboardInterrupt: observer.stop() observer.join()
额外注意事项
- 如果你要移动的文件正被Telegram等程序占用,需要等文件完全下载、程序释放文件占用后再执行移动操作
- 如果不需要监听实时移动,只需要一次性迁移所有文件,可以去掉watchdog相关的监听逻辑,直接执行遍历移动的代码即可
内容的提问来源于stack exchange,提问作者siavash
相关产品推荐
相关产品推荐

