Python文件自动整理工具详解

本文详细介绍如何使用Python构建自动化文件整理工具,包含完整的代码实现、文件分类逻辑、重复文件处理机制,以及如何在Windows系统上设置定时自动执行任务。

Python实现的文件夹整理工具

打开下载文件夹或其他文件夹时,你可能会发现无数不同类型的文件(图片、文档、安装程序等)混在一起,不得不花费大量时间寻找ChatGPT生成的作业PDF,想着"真麻烦",或者不得不手动整理20个PDF、10张图片和5个安装程序。我也经历过这种情况,因此决定创建一个脚本,让我可以继续偷懒,同时让文件保持完美有序。

这个使用Python的脚本可以为我完成这项工作。你可以直接在GitHub上查看它。

脚本工作原理

为了构建这个工具,我使用了几个Python库,一些是内置的(“标准库”),还有一个外部库用于在脚本执行时通知我。

步骤1:导入库

1
2
3
4
import os
import shutil
import sys
from win10toast import ToastNotifier
  • os(操作系统):允许我们检查文件或文件夹是否存在(os.path.exists),创建文件夹(os.makedirs),列出所有文件(os.listdir)并获取文件扩展名(os.path.splitext)。
  • shutil(Shell工具):允许我们将文件从一个地方移动到另一个地方(shutil.move())。
  • sys(系统):sys.executable让我知道脚本在哪里执行,这在编译为.exe文件时非常有用。
  • ToastNotifier(来自win10toast):这是外部库。它允许我们向Windows发送原生通知。使用pip install wintoast安装。

步骤2:文件映射

创建一个字典作为映射,其中每个键是我们想要创建的文件夹名称(例如"imagenes"),值是该文件夹中应包含的所有文件扩展名的列表。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
notificar = ToastNotifier() # 初始化通知器
tipos_de_archivo = {
    "imagenes": [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg"],
    "videos": [".mp4", ".avi", ".mov", ".mkv", ".webm"],
    "documentos": [".pdf", ".doc", ".docx", ".txt", ".xls", ".xlsx"],
    "ejecutables y sistema": [".exe", ".msi", ".bat", ".dll"],
    "comprimidos": [".zip", ".rar", ".7z", ".iso"],
    # ...其他类别也是如此...
    "Otros": [] # 特殊类别,用于不匹配的文件
}

步骤3:灵活配置(读取rutas.txt)

我不想每次想要添加新文件夹进行整理时都编辑脚本。因此,我让脚本读取一个配置文件rutas.txt

此函数打开该文件,读取每一行,如果写入的路径确实存在,则将其添加到列表中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
def obtener_rutas(ruta_actual, archivo='rutas.txt'):
    """
    获取写在config/rutas.txt文件中的路径
    """
    rutas_validas = []
    # 在'config'文件夹中查找.txt文件
    archivo_rutas = os.path.join(ruta_actual, 'config', archivo) 
    with open(archivo_rutas, 'r', encoding='utf-8') as rutas:
        for linea in rutas:
            ruta = linea.strip() # .strip()去除空白字符
            # 如果路径不为空且存在...
            if ruta and os.path.exists(ruta):
                rutas_validas.append(os.path.abspath(ruta))

    return rutas_validas

步骤4:处理重复文件

这是最重要的部分。如果我将tarea.pdf移动到"Documentos",但该文件夹中已存在tarea.pdf怎么办? 为此,有mover_archivo函数。

  • 尝试移动它:如果目标位置不存在该文件,则直接移动它(shutil.move)。
  • 如果已存在:
    1. 创建一个名为"DUPLICADOS"的文件夹。
    2. 为新文件重命名(例如从tarea.pdf改为tarea (1).pdf)。
    3. 查找可用的名称(如果tarea (1).pdf存在,则尝试tarea (2).pdf,依此类推)。
    4. 将重命名的文件移动到"DUPLICADOS"文件夹。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def mover_archivo(origen, destino):
    try:
        if not os.path.exists(destino):
            # 路径可用,正常移动
            shutil.move(origen, destino)
        else:
            # 冲突!文件已存在
            carpeta_duplicados = os.path.join(os.path.dirname(destino), "DUPLICADOS")
            os.makedirs(carpeta_duplicados, exist_ok=True)

            # 查找新名称的逻辑(例如"archivo (1).ext")
            contador = 1
            base, ext = os.path.splitext(os.path.basename(origen))
            nuevo_nombre = f"{base} ({contador}){ext}"
            nuevo_destino = os.path.join(carpeta_duplicados, nuevo_nombre)

            while os.path.exists(nuevo_destino):
                contador += 1
                nuevo_nombre = f"{base} ({contador}){ext}"
                nuevo_destino = os.path.join(carpeta_duplicados, nuevo_nombre)

            shutil.move(origen, nuevo_destino)
    except Exception:
        # 如果出现任何错误(例如文件正在使用),直接忽略
        # 这样脚本不会停止。
        pass

步骤5:整理功能

此函数遍历我们传递给它的文件夹:

  • 使用os.listdir(ruta)列出所有内容。
  • 如果是文件,在我们的"映射"(tipos_de_archivo)中查找其扩展名,并将其发送到mover_archivo函数。如果未找到扩展名,则将其发送到"Otros"。
  • 如果是文件夹(并且不是我们的类别文件夹之一,如"Imagenes"),则将其整个移动到名为"Carpetas"的文件夹中。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
def organizar_carpeta(ruta, tipos):
    for archivo in os.listdir(ruta):
        archivo_path = os.path.join(ruta, archivo)

        if os.path.isfile(archivo_path):
            # 是文件,查找扩展名
            extension = os.path.splitext(archivo_path)[1]
            for categoria, extensiones in tipos.items():
                if extension.lower() in extensiones:
                    destino = os.path.join(ruta, categoria, archivo)
                    break # 找到类别,跳出循环
            else:
                # 未找到,转到"Otros"
                destino = os.path.join(ruta, "Otros", archivo)
            mover_archivo(archivo_path, destino)

        elif os.path.isdir(archivo_path) and not archivo in tipos.keys():
            # 是文件夹,移动到"Carpetas"
            destino = os.path.join(ruta, "Carpetas", archivo)
            mover_archivo(archivo_path, destino)

步骤6:启动运行

if __name__ == "__main__":块是实际执行所有操作的部分。

  • 首先,从我们的rutas.txt获取所有要整理的路径。
  • 然后,对每个路径进行for循环,并调用organizar_carpeta
  • 完成后,使用notificar.show_toast()发送通知,告诉我执行已完成。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
if __name__ == "__main__":
    # ...(查找ruta_script和ruta_icon的代码)...

    # 1. 从.txt获取路径
    rutas = obtener_rutas(ruta_script)

    # 2. 整理每一个路径
    for rt in rutas:
        organizar_carpeta(rt, tipos_de_archivo)

    # 3. 通知
    notificar.show_toast(
        "文件整理器",
        "✅ 下载文件夹中的文件已整理完成!",
        icon_path= ruta_icon,
        duration=10,
    )

注意:我使用Windows,因此wintoast适用于通知。如果你使用Linux,可以尝试使用其他库或工具,或者直接跳过此步骤和wintoast的导入。

使用方法

  1. 访问我的GitHub仓库fiedri’s Toolbox
  2. 确保已安装Python和必要的库:pip install wintoast
  3. 在脚本旁边创建一个config文件夹,并在其中创建一个rutas.txt文件。
  4. rutas.txt中,写入要整理的文件夹的完整路径(例如C:\Users\fiedri\Downloads),每行一个。
  5. 运行脚本。

如何自动化脚本(Windows)

为了让脚本自动运行,无需任何操作。最简单的方法是使用任务计划程序(Task Scheduler)。

  1. 在Windows开始菜单中搜索"任务计划程序"。
  2. 在右侧面板中,点击"创建基本任务…"。
  3. 给它起个名字,并选择希望它何时运行。我将其配置为在我知道电脑会开机的特定时间每周运行。
  4. 选择"启动程序"。
  5. 配置:
    • 在"程序/脚本"中,查找并选择你的python.exe(通常位于C:\Python310\python.exe)。
    • 在"添加参数"中,粘贴脚本的完整路径:C:\ruta\a\tu\organizer_downloads_auto.py
    • 可选:如果将脚本编译为.exe文件(我做了),只需在"程序/脚本"中放入该.exe的路径即可。
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计