用Python做一个文件夹整理工具

news2025/1/14 1:07:08

文章目录

    • 简介
    • 文件夹对话框
    • 文件映射组件
    • 完整组件

简介

我们的目的是做一个像下面这样的工具,前面两个输入框,用于输入源路径和目标路径,下面的图片、视频、音乐表示在目标路径中创建的文件夹,后面的文件后缀,表示将这类文件移动到对应的文件夹中,加减号可以新增或删除文件夹。

在这里插入图片描述

文件夹对话框

第一步,实现源路径和目标路径的输入输出,从而需要自定义一个组件,代码如下,其及具体实现逻辑,可以参考:自定义文件选择按钮

import tkinter as tk
import tkinter.ttk as ttk
from tkinter.filedialog import (askopenfilename,
    askopenfilenames, askdirectory, asksaveasfilename)
from tkinter.colorchooser import askcolor

class DialogButton(ttk.Frame):
    def __init__(self, master, 
        height, widthL, widthR, logtype, label=None, text=None, 
        frmDct={}, btnDct={}, enyDct={}, logDct={}):
        w = widthL + widthR
        super().__init__(master, 
            height=height, width = w, **frmDct)
        self.pack(fill=tk.X)

        self.text = tk.StringVar() if not text else text
        ttk.Entry(self, width=widthL, textvariable=self.text, 
            **enyDct).pack(side=tk.LEFT, fill = tk.X, expand=True)
        
        ttk.Button(self, width=widthR, 
            text=self.setLabel(logtype, label),
            command = self.Click, **btnDct).pack(side=tk.RIGHT, padx=5)
        self.logtype = logtype
        self.logDct = logDct

    def setLabel(self, key, label=None):
        if label:
            return label
        labelDct = {
            "文件"   : "选择文件",
            "文件夹" : "选择路径",
            "多文件" : "选择多个文件",
            "保存" : "存储路径",
            "颜色"   : "选择颜色",
        }
        return labelDct[key]

    def Click(self):
        typeDct = {
            "文件"  : askopenfilename,
            "文件夹": askdirectory,
            "多文件": askopenfilenames,
            "保存"  : asksaveasfilename,
            "颜色"  : askcolor,
        }
        text = typeDct[self.logtype](**self.logDct)
        if self.logtype == "颜色":
            text = text[1]
        self.text.set(text)

    def get(self):
        return self.text.get()

    def set(self, txt):
        self.text.set(txt)

文件映射组件

关于文件夹整理这个功能,此前其实做过无图形界面的版本:
Python整理下载文件夹,第一步自然是做一个文件映射字典,

F_DCT = {
    "图片"  : [".jpg", ".png", ".jpeg", ".gif"],
    "视频"  : [".mp4", ".mkv"],
    "音乐"  : [".mp3", ".wav"],
    "文档"  : [".pdf"],  
    "文献"  : [".caj"],
    "文本"  : [".csv", ".txt"],
    "源码"  : [".py", ".c", ".cpp", ".php"],
    "office": [".docx",".xlsx", ".pptx", ".doc", ".ppt", ".xls"],
    "压缩包": [".zip", ".tgz", ".rar", ".tar", ".7z", ".gz"],
    "安装包": [".msi", ".exe"],
}

然后就是工具的核心内容,文件映射组件,主要由左右两部分组成,左侧是文件夹名,右侧是对应的文件后缀。从这两个子组件出发,可以为其设置初始化参数以及方法。先看源码,再逐段解析

import tkinter as tk
import tkinter.ttk as ttk
from ctrls import DialogButton
import os
import shutil
pJoin = os.path.join
pExist = os.path.exists

from pathlib import Path

class ExFolder(ttk.Frame):
    def __init__(self, master, 
        folder=None, ex=None, dst=None, **options):
        super().__init__(master, **options)
        self.pack()

        self.folder = tk.StringVar()
        if folder : self.setFolder(folder)
        self.ex = tk.StringVar()
        if ex : self.setEx(ex)
        self.setDst(dst)

        self.initWidgets()

    def initWidgets(self):
        ttk.Entry(self, textvariable=self.folder, 
            width=10).pack(side=tk.LEFT, padx=2)    
        ttk.Entry(self, textvariable=self.ex
            ).pack(side=tk.LEFT, fill=tk.X, expand=True)

    def getFolder(self):
        return self.folder.get()

    def setFolder(self, f):
        self.folder.set(f)
    
    def getEx(self):
        exs = self.ex.get().split(",")
        for i in range(len(exs)):
            exs[i] = exs[i].strip()
        return exs
    
    def setEx(self, exs):
        if type(exs)==list:
            exs = ', '.join([ex.strip() for ex in exs])
        self.ex.set(exs)
    
    def mvFile(self, src):
        try:
            shutil.move(src, self.dst)
        except Exception as e:
            self.err = print(e)
    
    # 设置目标文件夹
    def setDst(self, dst):
        if not dst:
            self.dst = None
            return
        self.dst = pJoin(dst, self.getFolder())
        if not pExist(self.dst):
            os.makedirs(self.dst)
        self.errs = {}

首先,folder和ex分别是左右两个组件对应的可变文本,为了便于更新和调用,类中设计了两组、四对便携方法getFolder, setFolder和getEx和setEx。由于Folder中的内容就是文件夹本身,所以设置和读取方法仅仅是StringVar的二次封装,而ex中的内容则不然,需要对文本进行分割,并且实现字符串到列表的转换。

mvFile和setDst是组件的核心功能,分别用于设置目标路径并移动。之所以为目标文件夹设置安排了一个独立方法,是因为目标文件夹不一定存在,可能涉及到递归创建的过程。

完整组件

最后,是整个组件的布局,源码如下,其中撤销功能并未实现。

class FolderTools(ttk.Frame):
    def __init__(self, master, fDct=F_DCT, **options):
        super().__init__(master, **options)
        self.pack()
        self.fDct = fDct

        self.initWidgets()
        self.fEnys = []
        self.exEnys = []

    def setDct(self, fDct):
        self.fDct = fDct
        self.exDct = {}
        for k,v in self.fDct.items():
            exDct.update({ex:k for ex in v})

    def initWidgets(self):
        self.exForders = []
        pDct = dict(side=tk.TOP, expand=True, fill=tk.X)
        self.srcFolder = DialogButton(self, 5, 25, 8, 
                                      "文件夹", label="源路径")
        self.srcFolder.pack(**pDct)
        self.dstFolder = DialogButton(self, 5, 25, 8, 
                                      "文件夹", label="目标路径")
        self.dstFolder.pack(**pDct)

        btns = ttk.Frame(self)
        btns.pack(**pDct)
        ttk.Button(btns, text="➕ ", 
            command=self.btnAddFolder).grid(row=0,column=0)
        ttk.Button(btns, text="➖", 
            command=self.btnDelFolder).grid(row=0,column=1)
        ttk.Button(btns, text="移动", 
            command=self.btnMove).grid(row=0,column=2)
        ttk.Button(btns, text="撤销", 
            command=self.btnMove).grid(row=0,column=3)

        self.exFrm = ttk.LabelFrame(self, text="文件夹映射表")
        self.exFrm.pack(**pDct)

        for k, v in self.fDct.items():
            self.addFolders(self.exFrm, k, v)

    def btnAddFolder(self):
        self.addFolders(self.exFrm, None, None)

    def addFolders(self, frm, folder, exs):
        ef = ExFolder(frm, folder, exs)
        ef.pack(side=tk.TOP, expand=True, fill=tk.X, padx=2, pady=1)
        self.exForders.append(ef)

    def btnDelFolder(self):
        if len(self.exForders) == 0: return
        self.exForders[-1].pack_forget()
        del self.exForders[-1]
    
    def setExDct(self):
        self.exDct = {}
        for ef in self.exForders:
            self.exDct.update({key:ef for key in ef.getEx()})

    def btnMove(self):
        src = self.srcFolder.get()
        dst = self.dstFolder.get()
        if dst=="": dst = src

        # 设置后缀映射字典 ex:ExFolder
        exDct = {}
        for ef in self.exForders:
            exDct.update({ex:ef for ex in ef.getEx()})
            ef.setDst(dst) # 设置目标文件夹

        files = os.listdir(src)
        for f in files:
            p = pJoin(src, f)
            ex = Path(p).suffix.lower()
            if ex in exDct:
                exDct[ex].mvFile(p)

三个已经实现的功能按钮,➕用于新增一个文件夹映射组件,➖则移除最后一个映射组件。移除组件时需要注意,不仅仅要把组件解绑,还要把组件对应的实例删掉。

核心功能被绑定在移动按钮上,首先读取源路径和目标路径,如果目标路径未输入,就在源路径下工作。

接下来,将文件映射组件重新拆解为映射字典,最后调用对应组件的mvFile方法,实现所有文件的移动。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1104910.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML 表格及练习

表格 概述 表格是一种二维结构,横行纵列。 由单元格组成。 表格是一种非常“强” 的结构: 每一行有相同的列数(单元格),每一列有相同的行数(单元格) 同一列的单元格,宽度&#…

《实验细节》使用PEFT库常见错误

《实验细节》使用PEFT库常见错误 安装问题常用命令使用问题问题1安装问题 首先给出用到的网站 更新NVIDIA网站https://www.nvidia.com/Download/index.aspx 2. 使用PEFT的优秀demo https://www.philschmid.de/fine-tune-flan-t5-peft 3. 下载一些库的必备网站 https://pypi.or…

(完全解决)latex如何设置某段文字向右对齐

开门见山,老子就是想要下图中日期的效果,可以看到,日期向右对齐。 很多人给的是下面这个方案: \begin{flushright}Sep 2020-July 2023 \end{flushright}但是试过了好像不行,其是换一行,然后向右对齐。 …

下拉选择器的树状结构图

类似&#xff1a;【Vue-Treeselect 和 vue3-treeselect】树形下拉框 一&#xff1a;图 二&#xff1a;如果有多层级的数据结构&#xff0c;可以用treeselect插件实现 1、安装&#xff1a; npm install --save riophae/vue-treeselect 2、实现&#xff1a; <el-form ref&qu…

深入了解RPA业务流程自动化的关键要素

在RPA业务流程自动化实施过程中&#xff0c;哪些因素起着至关重要的作用&#xff1f;这其实没有一个通用的答案&#xff0c;每一个RPA业务流程自动化的部署&#xff0c;都需要结合具体场景去调整&#xff0c;并且进行全面的规划。 首当其冲是要关注以下几点&#xff1a; 1、专…

想提高工作效率?这里有五款实用工具推荐

​ 想提高工作效率&#xff1f;这里有五款实用工具推荐&#xff01;搜索一下就能下载到。 1.鼠标控制——MouseInc ​ MouseInc是一款创新的鼠标控制软件&#xff0c;可以让用户通过手势、声音或眼睛来控制鼠标的移动和点击。MouseInc利用了人工智能和计算机视觉的技术&#…

景联文科技语音数据标注:AUTO-AVSR模型和数据助力视听语音识别

ASR、VSR和AV-ASR的性能提高很大程度上归功于更大的模型和训练数据集的使用。 更大的模型具有更多的参数和更强大的表示能力&#xff0c;能够捕获到更多的语言特征和上下文信息&#xff0c;从而提高识别准确性&#xff1b;更大的训练集也能带来更好的性能&#xff0c;更多的数据…

九章云极DataCanvas多模态大模型平台实践与思考

导读&#xff1a;本文将分享九章云极DataCanvas在多模态大模型平台方面的一些思考和实践。 今天的介绍会围绕下面四点展开&#xff1a; 多模态大模型的历史发展 九章云极DataCanvas的多模态大模型平台 九章云极DataCanvas多模态大模型的实践 对未来的思考与展望 ▌多模态…

单片机点亮led管(01)

如何开始学习单片机 1&#xff1a;实践第一 2&#xff1a;补充必要的理论知识&#xff0c;缺什么补什么 3&#xff1a;做工程积累经验&#xff08;可以在网络上收集题目&#xff0c;也可以有自己的想法大胆的实验&#xff09; 单片机是什么&#xff1f; 单片机&#xff08…

活动回顾 | MatrixOne 在 SaaS 企服领域的应用解读

9月3日&#xff0c;矩阵起源产品总监邓楠于 QCon 北京站首次分享了 MatrixOne 在 SaaS 企服领域的应用&#xff0c;本篇文章将对该次分享进行回顾。 Part 1 MatrixOne 是什么&#xff1f; MatrixOne 是一款面向未来的超融合异构云原生数据库管理系统。通过全新从零自研的统一…

Pika v3.5.1发布!

导读Pika 社区很高兴宣布&#xff0c;我们今天发布已经过我们生产环境验证 v3.5.1 版本&#xff0c;https://github.com/OpenAtomFoundation/pika/releases/tag/v3.5.1 。 该版本不仅做了很多优化工作&#xff0c;还引入了多项新功能。这些新功能包括 动态关闭 WAL、Replicati…

如何打造品牌爆文,小红书爆文封面教程

在小红书平台&#xff0c;爆文其实是核心竞争力&#xff0c;你的流量取决于你生产爆文的稳定程度。而对于一篇文章而言&#xff0c;最重要的即是封面。今天来分享下如何打造品牌爆文&#xff0c;小红书爆文封面教程&#xff01; 1.了解用户人群特点 深入了解目标用户人群的特点…

数字化 | 智能电子日历

想要一款随时随地都能掌握日期的电子日历吗&#xff1f; WiFi通信&#xff0c;实时更新&#xff0c;超低功耗&#xff0c;可充电&#xff0c;超长续航&#xff0c;电子纸&#xff0c;黑白红三色显示的电子日历&#xff0c;就是你的最佳选择&#xff01; 无论是在办公室、家中或…

更新 | 持续开源 迅为RK3568驱动指南第十一篇-pinctrl子系统

《iTOP-RK3568开发板驱动开发指南》更新&#xff0c;本次更新内容对应的是驱动&#xff08;第十一期_pinctrl子系统-全新升级&#xff09;视频&#xff0c;后续资料会不断更新&#xff0c;不断完善&#xff0c;帮助用户快速入门&#xff0c;大大提升研发速度。 文档教程更新至第…

模拟退火算法求解TSP问题(python)

模拟退火算法求解TSP的步骤参考书籍《Matlab智能算法30个案例分析》。 问题描述 TSP问题描述在该书籍的第4章 算法流程 部分实现代码片段 坐标轴转换成两点之间直线距离长度的代码 coordinates np.array([(16.47, 96.10),(16.47, 94.44),(20.09, 92.54),(22.39, 93.37),(2…

详解--计算机中的索引(包含 数据库,磁盘)

1. 索引概念 1.1 什么是索引 例子 当我们看一本书时&#xff0c;目录就相当于对照表&#xff0c;通过目录可以快速找到要看的内容。拓展 索引就相当于书的目录。 索引是有序的索引在计算机领域中是一种数据结构 1.2 索引的作用 主要用于提高查询效率。 例子&#xff1a; …

EasyExcel导出带有下拉框的表头模板

1.接口层 ApiOperation("其他费用配置-模版下载")GetMapping("/downloadTemplate")public void downloadTemplate(HttpServletResponse response) {try {List<String> list Arrays.asList("集团", "平台", "部门", &…

欧盟反垄断法的改变:对跨境电商的冲击和机遇

2024年&#xff0c;欧盟反垄断法将经历一场革命性的改变&#xff0c;这对于跨境电商来说是一个重大的法规转折点。长达数十年的联合体集体豁免条例&#xff08;CBER&#xff09;即将失效。 这意味着货运公司将不再享受欧盟针对反竞争协议规则的特殊待遇。这一法规的变革将对跨…

【精选】目前我国网络安全人才市场状况

网络安全人才市场状况 本章以智联招聘多年来形成的丰富的招聘、求职信息大数据为基础&#xff0c;结合了奇安信集团 在网络安全领域多年来的专业研究经验&#xff0c;相关研究成果具有很强的代表性。对涉及安全人才 的全平台招聘需求与求职简历进行分析&#xff08;注&#xf…

(十)Python异常处理机制

程序运行时常会碰到一些错误&#xff0c;例如除数为 0、年龄为负数、数组下标越界等&#xff0c;这些错误如果不能发现并加以处理&#xff0c;很可能会导致程序崩溃。 和 C、Java 这些编程语言一样&#xff0c;Python 也提供了处理异常的机制&#xff0c;可以让我们捕获并处理…