iT邦幫忙

2025 iThome 鐵人賽

DAY 9
0
Software Development

軟體開發養成計畫:以小程式實作深化開發能力系列 第 9

[Day9]懶人救星:Python 幫你自動分類檔案

  • 分享至 

  • xImage
  •  

前言

你的桌面是否經常被各種檔案佔滿,看起來雜亂無章,不知從何整理起呢?今天的主題正好能幫你解決這個困擾。
檔案整理器 —— 一個能自動化分類檔案的小工具。透過它,我們不需要再花時間一個一個拖曳檔案,只要設定好規則,它就能依照副檔名或檔案類型,幫忙自動歸類到對應的資料夾。
除了節省時間,檔案整理器最大的優勢是降低遺漏和錯放檔案的機率,特別適合經常需要下載、整理大量檔案的使用者。
接下來,我們一起來看怎麼實作屬於自己的檔案整理小程式,讓桌面不再成為堆積吧!


這次使用了Python內建的os和和Sheil模組來處理作業系統層面的檔案操作。

1.檔案與路徑操作(os & shutil)

  • os:它就像是我們與電腦作業系統溝通的橋樑。
    我們可以用它來:
    1.讀取資料夾 (os.listdir)
    2.檢查路徑是否存在(os.path.exists)
    3.判斷是檔案還是資料夾 (os.path.isdir)
    4.組合路徑 (os.path.join)
    有了這些功能,就能精準地抓到每個檔案的位置。

  • shutil:這個模組則是搬運小能手!最常用的功能就是移動檔案 shutil.move,可以把檔案從原本亂七八糟的資料夾,直接搬到分類好的新資料夾,整個自動整理的流程就靠它搞定了。

2.GUI 介面與事件處理(tkinter)

自從上次學會怎麼做 GUI 介面後,我現在幾乎寫程式都離不開它了XD
這次我用到的功能主要有:

  • 建立視窗跟元件
    先用** tk.Tk() **建立一個主視窗,然後在上面擺上按鈕 (tk.Button) 和文字標籤 (tk.Label),就像在布置小工具一樣。
  • 和使用者互動:Tkinter 的重點就是事件處理!我們可以幫每個按鈕加上對應的 command,這樣一按下去,程式就會自動執行我們設定好的功能。比如「點擊整理」開始分類,或「點擊離開」直接關閉視窗,超直覺~
  • 叫出系統的檔案總管:tkinter.filedialog 真的是神器,按個按鈕就能直接跳出作業系統的檔案總管,讓使用者自己選資料夾,這樣不只方便,也不用再擔心手動輸入路徑會打錯了。

3.程式碼實作

(1)模組匯入

import os
import shutil
import tkinter as tk
from tkinter import filedialog, messagebox
  • os:處理路徑、檔案/資料夾檢查。
  • shutil:負責搬移檔案。
  • tkinter:建立 GUI 介面,讓使用者能透過視窗操作程式。
  • filedialog / messagebox:分別用來叫出檔案總管 & 彈出提示視窗。

(2)定義檔案類型

file_types = {
    'Images': ['.jpg', '.jpeg', '.png', '.gif', '.bmp'],
    'Documents': ['.doc', '.docx', '.pdf', '.txt', '.xlsx', '.pptx'],
    'Archives': ['.zip', '.rar', '.7z'],
    'Videos': ['.mp4', '.avi', '.mov'],
    'Audio': ['.mp3', '.wav', '.flac'],
    'Code': ['.py', '.js', '.html', '.css', '.c', '.cpp', '.java'],
    'Executables': ['.exe', '.dmg', '.pkg']
}
  • 建立一個字典 (dictionary),把常見的副檔名歸類到不同的類別,之後程式會依照副檔名來判斷檔案要放到哪個資料夾。

(3)核心整理函式

def organize_files(source_folder):
    if not os.path.exists(source_folder):
        return ["錯誤:指定的資料夾不存在。"]

    results = []
    created_folders = set()

    for filename in os.listdir(source_folder):
        file_path = os.path.join(source_folder, filename)

        if os.path.isdir(file_path):
            continue

        file_extension = os.path.splitext(filename)[1].lower()
        destination_folder = 'Others'
        
        for folder, extensions in file_types.items():
            if file_extension in extensions:
                destination_folder = folder
                break
        
        target_path = os.path.join(source_folder, destination_folder)

        if not os.path.exists(target_path):
            os.makedirs(target_path)
            if destination_folder not in created_folders:
                results.append(f"已建立資料夾:{destination_folder}")
                created_folders.add(destination_folder)

        try:
            shutil.move(file_path, os.path.join(target_path, filename))
            results.append(f"已移動檔案:{filename} -> {destination_folder}")
        except shutil.Error as e:
            results.append(f"移動檔案時出錯 {filename}:{e}")
    
    return results
  • os.path.splitext(filename)[1].lower() :取得副檔名,並轉小寫避免大小寫問題(例如 .JPG / .jpg)。
  • 比對 file_types,決定檔案要放到哪個資料夾;沒符合就放進 Others。
  • os.makedirs(target_path):如果沒有該分類的資料夾,就自動新建。
  • shutil.move():把檔案搬到對應的分類資料夾。

(4)GUI 操作函式

def organize_files_gui():
    source_path = filedialog.askdirectory()
    if not source_path:
        result_text.set("")
        return
    
    result_text.set("開始整理中...\n\n")
    root.update_idletasks()  # 即時刷新 GUI
    
    move_results = organize_files(source_path)

    final_result = "整理結果:\n"
    if move_results:
        final_result += "\n".join(move_results)
    else:
        final_result += "沒有找到需要整理的檔案。"
        
    result_text.set(final_result)
    messagebox.showinfo("整理完成", "檔案整理已完成!")
  • filedialog.askdirectory():彈出檔案總管,選擇要整理的資料夾,取代手動輸入路徑。
  • root.update_idletasks():先顯示「開始整理中」,避免使用者以為程式卡住。
  • organize_files() 的回傳結果整理好,更新到介面。
  • messagebox.showinfo 彈出視窗通知。

(5)GUI 視窗設計

if __name__ == "__main__":
    root = tk.Tk()
    root.title("檔案整理小工具")
    root.geometry("400x450")
    root.configure(bg="#f0f0f0")

    # 操作說明
    label = tk.Label(main_frame, text="點擊按鈕選擇資料夾,自動整理檔案。")
    label.pack(pady=(0, 15))

    # 整理按鈕
    organize_button = tk.Button(main_frame, text="選擇資料夾並整理", command=organize_files_gui)
    organize_button.pack()

    # 離開按鈕
    exit_button = tk.Button(main_frame, text="離開程式", command=root.destroy)
    exit_button.pack()

    # 顯示整理結果
    result_text = tk.StringVar()
    result_label = tk.Label(result_frame, textvariable=result_text, justify="left", wraplength=320)
    result_label.pack()

    root.mainloop()
  • 用 **StringVar() **綁定 Label,讓結果能即時更新在介面上。
  • root.mainloop() 讓程式持續監聽使用者操作。

4.展示成果

21
22

5.開發過程遇到的難題

(1)程式閃退

當我把程式碼打包成 .exe 後,發現系統會立即關閉視窗,導致無法確認程式是否執行成功。如果想要再次分類檔案,也必須重新開啟 .exe,使用上就顯得不夠靈活。
為了解決這個問題,我在程式中加入了一個重複迴圈,並結合 GUI 設計,讓使用者只要按下「離開」按鈕,就能觸發 break 跳出迴圈。這樣一來,不僅能保留足夠的時間閱讀程式輸出的訊息,也能在同一個程式執行期間重複使用功能,而不用每次都重新開啟檔案,實用性大大提升!

(2)手動輸入路徑的痛點

在最初的版本中,使用者需要手動找到想要整理的資料夾,再將其路徑複製並貼到程式中。這樣的操作不僅繁瑣,還容易因為輸入錯誤而造成程式失敗。
為了解決這個問題,我引入了 tkinter.filedialog 模組,它能直接呼叫作業系統的檔案總管,讓使用者只需要點擊按鈕,就能彈出資料夾選擇視窗。選擇好資料夾後,程式會自動取得路徑並傳回,完全不需要額外複製或貼上。
這樣一來,不但節省了操作時間,也讓整個使用流程更直覺、更不容易出錯!


這次的檔案整理小程式,不只是把檔案整理乾淨,更讓我體驗到程式設計結合使用者思維的樂趣。一鍵整理檔案的功能雖然小巧,但每天使用都能省下不少時間,那種即時的成就感真的很棒!
也讓我深刻感受到,「設計流程」比單純寫程式更重要:先分類檔案類型 → 寫整理函式 → GUI 操作串接 → 處理錯誤 → 顯示結果,每一步都得考慮使用者體驗。總結來說這是一個小巧卻非常實用的專案呢!


上一篇
[Day8]隨機數與模擬應用(random 模組)
系列文
軟體開發養成計畫:以小程式實作深化開發能力9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言