当前位置: 首页 > news >正文

python进行磁盘文件迁移,不影响软件使用

部分软件默认在C盘占用了很大的磁盘. 将文件夹迁移到其他盘,原地留下软连接,软件启动的之后,会访问到迁移后的位置,不影响软件适合用

poython脚本

importctypesimportosimportshutilimportsubprocessimportthreadingimporttkinterastkfromctypesimportwintypesfrompathlibimportPathfromtkinterimportfiledialog,messagebox,ttk SEE_MASK_NOCLOSEPROCESS=0x00000040SW_HIDE=0ERROR_CANCELLED=1223classSHELLEXECUTEINFO(ctypes.Structure):_fields_=[("cbSize",wintypes.DWORD),("fMask",ctypes.c_ulong),("hwnd",wintypes.HWND),("lpVerb",wintypes.LPCWSTR),("lpFile",wintypes.LPCWSTR),("lpParameters",wintypes.LPCWSTR),("lpDirectory",wintypes.LPCWSTR),("nShow",ctypes.c_int),("hInstApp",wintypes.HINSTANCE),("lpIDList",ctypes.c_void_p),("lpClass",wintypes.LPCWSTR),("hkeyClass",wintypes.HKEY),("dwHotKey",wintypes.DWORD),("hIconOrMonitor",wintypes.HANDLE),("hProcess",wintypes.HANDLE),]defnormalized(path):returnos.path.normcase(os.path.abspath(path))defis_same_or_child(path,parent):try:returnos.path.commonpath([normalized(path),normalized(parent)])==normalized(parent)exceptValueError:returnFalsedefrun_mklink_as_admin(link_path,target_path):command=subprocess.list2cmdline(["/c","mklink","/D",str(link_path),str(target_path)])info=SHELLEXECUTEINFO()info.cbSize=ctypes.sizeof(info)info.fMask=SEE_MASK_NOCLOSEPROCESS info.lpVerb="runas"info.lpFile="cmd.exe"info.lpParameters=command info.nShow=SW_HIDEifnotctypes.windll.shell32.ShellExecuteExW(ctypes.byref(info)):error=ctypes.get_last_error()iferror==ERROR_CANCELLED:raiseRuntimeError("已取消管理员授权。")raisectypes.WinError(error)try:ctypes.windll.kernel32.WaitForSingleObject(info.hProcess,0xFFFFFFFF)exit_code=wintypes.DWORD()ifnotctypes.windll.kernel32.GetExitCodeProcess(info.hProcess,ctypes.byref(exit_code)):raisectypes.WinError()ifexit_code.value!=0:raiseRuntimeError(f"mklink 执行失败,退出代码:{exit_code.value}")finally:ctypes.windll.kernel32.CloseHandle(info.hProcess)classFolderMigrator(tk.Tk):def__init__(self):super().__init__()self.title("文件夹迁移")self.geometry("680x250")self.minsize(600,250)self.source_var=tk.StringVar()self.target_var=tk.StringVar()self.status_var=tk.StringVar(value="请选择原文件夹和目标文件夹")self.columnconfigure(1,weight=1)self._build_ui()def_build_ui(self):padding={"padx":14,"pady":10}ttk.Label(self,text="原文件夹").grid(row=0,column=0,sticky="w",**padding)ttk.Entry(self,textvariable=self.source_var).grid(row=0,column=1,sticky="ew",pady=10)ttk.Button(self,text="选择...",command=self.choose_source).grid(row=0,column=2,**padding)ttk.Label(self,text="目标文件夹").grid(row=1,column=0,sticky="w",**padding)ttk.Entry(self,textvariable=self.target_var).grid(row=1,column=1,sticky="ew",pady=10)ttk.Button(self,text="选择...",command=self.choose_target).grid(row=1,column=2,**padding)ttk.Separator(self).grid(row=2,column=0,columnspan=3,sticky="ew",padx=14,pady=6)ttk.Label(self,textvariable=self.status_var).grid(row=3,column=0,columnspan=3,sticky="w",padx=14,pady=8)self.migrate_button=ttk.Button(self,text="迁移并创建链接",command=self.start_migration)self.migrate_button.grid(row=4,column=0,columnspan=3,pady=14)defchoose_source(self):path=filedialog.askdirectory(title="选择要迁移的原文件夹")ifpath:self.source_var.set(path)defchoose_target(self):path=filedialog.askdirectory(title="选择迁移到的目标文件夹")ifpath:self.target_var.set(path)defvalidate_paths(self):source_text=self.source_var.get().strip()target_text=self.target_var.get().strip()ifnotsource_textornottarget_text:raiseValueError("请选择原文件夹和目标文件夹。")source=Path(source_text)target_parent=Path(target_text)ifnotsource.is_dir():raiseValueError("原文件夹不存在或不是文件夹。")ifsource.is_symlink():raiseValueError("原文件夹已经是符号链接,不能再次迁移。")ifnottarget_parent.is_dir():raiseValueError("目标文件夹不存在或不是文件夹。")destination=target_parent/source.nameifnormalized(source)==normalized(destination):raiseValueError("目标位置与原文件夹位置相同。")ifdestination.exists()ordestination.is_symlink():raiseFileExistsError(f"目标文件夹中已经存在同名项目:\n{destination}")ifis_same_or_child(target_parent,source):raiseValueError("目标文件夹不能位于原文件夹内部。")returnsource,destinationdefstart_migration(self):try:source,destination=self.validate_paths()except(ValueError,FileExistsError)asexc:messagebox.showerror("无法迁移",str(exc))returnconfirmed=messagebox.askyesno("确认迁移","将执行以下操作:\n\n"f"剪切:{source}\n"f"到:{destination}\n\n"f"然后创建目录链接:\n{source}->{destination}",)ifnotconfirmed:returnself.migrate_button.config(state="disabled")self.status_var.set("正在迁移文件夹,请勿关闭程序...")threading.Thread(target=self.migrate,args=(source,destination),daemon=True).start()defmigrate(self,source,destination):moved=Falsetry:shutil.move(str(source),str(destination))moved=Trueself.after(0,self.status_var.set,"迁移完成,正在请求管理员权限...")run_mklink_as_admin(source,destination)exceptExceptionasexc:rollback_error=Noneifmovedanddestination.exists()andnotsource.exists():try:shutil.move(str(destination),str(source))exceptExceptionasrollback_exc:rollback_error=rollback_exc text=str(exc)ifrollback_error:text+=("\n\n自动还原也失败了,请手动处理:"f"\n当前文件夹:{destination}"f"\n还原位置:{source}"f"\n原因:{rollback_error}")elifmoved:text+="\n\n已将文件夹自动移回原位置。"self.after(0,self.finish_error,text)returnself.after(0,self.finish_success,source,destination)deffinish_success(self,source,destination):self.migrate_button.config(state="normal")self.status_var.set("迁移和目录链接创建成功")messagebox.showinfo("迁移完成",f"文件夹已迁移到:\n{destination}\n\n"f"原位置已创建目录链接:\n{source}",)deffinish_error(self,text):self.migrate_button.config(state="normal")self.status_var.set("迁移失败")messagebox.showerror("迁移失败",text)if__name__=="__main__":ifos.name!="nt":raiseSystemExit("此工具仅支持 Windows。")FolderMigrator().mainloop()

运行命令

我的脚本名字叫 folder_migrator.py

python folder_migrator.py

打包命令

python-m PyInstaller-F-w-n"磁盘迁移"folder_migrator.py

使用

  1. 选择原文件夹和目标的文件夹,点击按扭之后,会弹窗进行确认


2. 点击确认,会迁移文件并调用cmd的管理员命令进行创建连接,若是原文件夹的迁移需要管理员权限,启动软件的时候,

http://www.rkmt.cn/news/1489951.html

相关文章:

  • 别再手动折腾了!用Docker Compose一键部署DzzOffice+OnlyOffice协同办公环境(附完整YAML配置)
  • 别再死记硬背Modbus帧格式了!用STM32CubeMX+RS485实战,5分钟搞懂RTU与ASCII区别
  • 别光发短信了!用Redis给你的SpringBoot短信验证码加个5分钟有效期
  • 保姆级教程:在STM32F4上配置CANopen SDO通信,从对象字典到代码实战
  • YOLO26涨点改进| ICASSP 2026| 独家卷积注意力改进篇 | 引入SSCL空间-光谱相关层模块,助力YOLO目标检测、小目标检测、图像增强/去噪/去雾、高光谱图像融合任务高效涨点
  • 【分享】Capsulyric[特殊字符]小米第三方状态栏工具|音乐歌词
  • SOLIDWORKS转CAD字体终极指南:TrueType vs SHX字体怎么选?避坑AutoCAD标准设置
  • 张家口AI服务供应商选择指南:五维评估帮企业找到最优智能化伙伴
  • 遗传图谱小白看过来:用MapChart和Excel 5分钟搞定你的第一条染色体标记图
  • 告别跳转混乱!手把手教你为嵌入式项目配置VSCode+Clangd的交叉编译头文件路径
  • 示波器抓毛刺?手把手教你用RLC模型计算防尖峰电阻的最佳阻值
  • 免费iOS激活锁绕过工具applera1n完整使用指南:让被锁iPhone重获新生
  • 信号处理实战:用Python复现EMD、VMD等5种自适应分解算法(附代码避坑)
  • 2026免费去水印工具推荐:在线/软件/手机APP全攻略
  • 从svg.panzoom卡顿到丝滑:一个被忽视的CSS属性如何毁掉你的SVG性能
  • 开源工具链实践:从内容创作到电商变现的自动化运营系统搭建
  • 【Python入门篇】函数作用域与名称空间详解
  • 十四周记录
  • 2026抖音地图店铺入驻技术要点与服务商参考:地图标注门店定位/抖音地图标注店铺入驻/实力盘点 - 优质品牌商家
  • FinalShell密码忘了别慌!手把手教你从本地文件找回服务器连接密码(附Java解密脚本)
  • 手把手教你:不写一行代码,在NX Block UI中直接‘借用’移动组件命令
  • 速通 计算理论(核心部分)
  • 生信小白避坑指南:你的多序列比对结果为啥‘乱七八糟’?可能是这5个输入细节没做好
  • AI组织进化论:拆解微软、英伟达、Anthropic与Open AI如何重写组织
  • 用C++解NOIP真题:P1068分数线划定,从冒泡到STL sort的四种解法对比
  • 纯棉四件套实测评测:纯棉三件套/四川棉被厂家/学生宿舍棉被/幼儿园棉被/应急棉絮/救灾棉絮棉被/救灾棉被棉絮/新疆长绒棉花被/选择指南 - 优质品牌商家
  • 2026年即墨区马桶疏通客服电话及服务指南 - 品牌排行榜
  • 保姆级教程:用安信可ESP32S3开发板,把闲置USB摄像头变成无线监控(支持手机浏览器查看)
  • Elasticsearch Python Client:官方出品,专治搜索对接的脏活
  • 告别命令行!在Docker Dashboard里点点鼠标就能管理你的Mac版SQL Server