快訊
2026-07-11
腳本自動化

Python 自動化第一課:批次改檔名、自動整理資料夾一次學會

約 9 分鐘閱讀

⚡ 站長快讀:核心重點

  • 文章屬性:教學實戰(腳本自動化入門)
  • 適用環境:Python 3.6 以上(Windows / macOS / Linux 通用)
  • 難易度 / 耗時:入門 / 約 20 分鐘
  • 核心結論:用 Python 內建的 os、pathlib、shutil 三個模組,就能批次改檔名、依副檔名或日期自動整理資料夾,不必額外安裝套件
  • 適用對象:每次都要手動改幾十個檔名、整理下載資料夾整理到懷疑人生的人

📌 快速答案

一句話答案:Python 批次改檔名的核心,是用 pathlib 的 glob() 掃出檔案、with_name() 算出新名字再 rename(),搭配先預覽(dry-run)與防覆蓋檢查,就能安全地一次改上百個檔名,並用 shutil 自動歸檔資料夾。

廣告

🧰 開始前的準備

  • 系統需求:Python 3.6 以上;本文範例在 Python 3.10 實際執行驗證,語法對 3.6~3.14 皆適用
  • 安裝:到 Python 官方下載頁 抓最新穩定版(2026-07 為 3.14.x);Windows 安裝時記得勾選「Add python.exe to PATH」
  • 權限需求:一般使用者即可,不需系統管理員
  • 需要工具:純內建模組(os、pathlib、shutil、datetime),不必 pip install 任何東西
  • 難度門檻:看得懂「資料夾路徑」和「複製、貼上、執行」就能開始

🔍 為什麼你需要這個?

你一定遇過這種場景:相機匯出的 IMG_3921.JPGIMG_4088.JPG,想全部改成「2026墾丁_001」開始的序號;或是下載資料夾塞了幾百個 PDF、圖片、壓縮檔全混在一起,想依類型分門別類。手動改一兩個還好,幾百個就是純粹的酷刑,而且很容易改到手殘、不小心蓋掉檔案。

這正是 Python 最擅長的雜事。批次改檔名、整理資料夾這種「規則明確、要重複很多次」的工作,寫一次腳本就能用一輩子,幾百個檔案幾秒鐘跑完。更關鍵的是,腳本可以「先預覽、再執行」,比在檔案總管裡一個個拖、一個個改,反而更安全、更不會出錯。

這是腳本自動化的第一課,站長我用最白話的方式,帶你把「手動地獄」變成「一鍵完成」。完全不想寫程式、只想用滑鼠點的人,可以先看站上這篇 PowerToys 九大功能教學(內含 PowerRename 圖形批次改名);想學會能自己客製的自動化,就繼續往下。


🛠️ 實戰步驟

⚠️ 動手前務必記住三件事:(1) 先拿「複製出來的測試資料夾」練習,別直接對唯一一份原始檔動手;(2) 每個改名、搬移腳本都先跑 dry-run(只印出、不執行) 確認結果再放行;(3) 重要檔案先備份。批次操作的威力和風險是一體兩面。

步驟一:先認識三個內建模組

先搞懂工具分工,後面就不會亂用。 Python 處理檔案主要靠三個標準模組,裝好 Python 就有:

  • pathlib:現代寫法的路徑物件,掃檔案、組路徑、換副檔名都靠它,是本文主角。
  • os:較底層的作業系統介面,os.walk() 遞迴掃資料夾、os.replace() 覆蓋搬移很好用。
  • shutil:高階檔案操作,搬移(move)、複製(copy)整個檔案或資料夾。

新手建議以 pathlib 為主,它把路徑當成物件操作,比舊式用字串拼路徑清楚太多。

步驟二:批次改檔名(先預覽,不要直接改)

批次改名的黃金守則:先 dry-run 印出「舊名 → 新名」對照,確認無誤再真的執行。 下面這段掃出資料夾裡所有 .JPG,幫每個檔名加上前綴,但只印出來、不改:

廣告
from pathlib import Path

folder = Path(r"C:\Users\你\Pictures\2026墾丁")  # 換成你的資料夾

# dry-run:先看結果,不動任何檔案
for p in sorted(folder.glob("*.JPG")):
    new = p.with_name("2026墾丁_" + p.name)
    print(f"{p.name}  ->  {new.name}")

確認印出來的對照沒問題,再把迴圈裡最後一行換成真的改名:

for p in sorted(folder.glob("*.JPG")):
    new = p.with_name("2026墾丁_" + p.name)
    p.rename(new)   # 真的執行改名

💡 為什麼用 with_name()? 它會保留原本的資料夾路徑,只換掉檔名部分,不必自己拼字串,也不會不小心把檔案搬到別的地方去。

想改成「乾淨的序號」也很簡單,用 enumerate 配補零格式 f"{i:03d}":

for i, p in enumerate(sorted(folder.glob("*.JPG")), start=1):
    new = p.with_name(f"photo_{i:03d}{p.suffix.lower()}")
    print(p.name, "->", new.name)   # 先預覽;要執行改成 p.rename(new)

p.suffix 是副檔名(含點,例如 .JPG),.lower() 順手把它轉成小寫。

步驟三:防覆蓋——批次改名最容易踩的雷

這是多數教學不會講、卻最容易搞丟檔案的地方。 依 Python 官方文件,Path.rename()Unix / macOS 上,若新檔名已存在會「靜默覆蓋」掉那個檔案;在 Windows 上則會直接拋出 FileExistsError。不管哪個平台,最保險的做法都是自己先檢查目標在不在:

def safe_rename(p: Path, new: Path):
    if new.exists():
        print("跳過(目標已存在):", new.name)
        return
    p.rename(new)
    print(f"{p.name} -> {new.name}")

# 範例:把檔名裡的空白換成底線
for p in folder.iterdir():
    if p.is_file() and " " in p.name:
        safe_rename(p, p.with_name(p.name.replace(" ", "_")))

如果你是「明知要覆蓋、故意要蓋」,才改用 os.replace(src, dst),它在各平台都會原子性地覆蓋。但預設請永遠用防覆蓋版本。

步驟四:依副檔名 / 日期自動整理資料夾

改完名字,順手把散落的檔案分門別類。 下面這段掃過資料夾,依副檔名建立子資料夾(jpg、pdf、csv…)再把檔案搬進去,用的是 shutil.move:

廣告
import shutil
from pathlib import Path

folder = Path(r"C:\Users\你\Downloads")

for p in folder.iterdir():
    if p.is_file():
        sub = folder / p.suffix.lstrip(".").lower()  # 例如 .PDF -> pdf
        sub.mkdir(exist_ok=True)                      # 沒有就建立
        shutil.move(str(p), str(sub / p.name))

想改成「依修改日期」歸檔(常用於照片、發票),把子資料夾名稱換成年月即可:

import shutil, datetime
from pathlib import Path

folder = Path(r"C:\Users\你\Downloads")

for p in folder.iterdir():
    if p.is_file():
        d = datetime.datetime.fromtimestamp(p.stat().st_mtime)
        sub = folder / d.strftime("%Y-%m")   # 例如 2026-07
        sub.mkdir(exist_ok=True)
        shutil.move(str(p), str(sub / p.name))

💡 exist_ok=True 是什麼? 建立資料夾時,如果它已經存在就不要報錯、直接沿用。少了這個參數,同一支腳本第二次跑就會炸。

步驟五:驗證結果

跑完一定要回頭確認,別「以為」成功了。 兩個最快的檢查:

  • 直接在檔案總管打開資料夾,看檔名與分類是否如預期。
  • 或用一行 Python 印出目前結構:for p in sorted(folder.iterdir()): print(p.name)

如果你要處理的是「資料夾裡還有子資料夾」的巢狀結構,把 folder.iterdir() 換成 os.walk(folder) 就能遞迴掃到底,相容所有 Python 版本。


🔬 底層機制:pathlib 到底幫你做了什麼?

知道 pathlib 在幹嘛,你才不會退回去用容易出錯的字串拼路徑。 早期 Python 處理路徑是把它當普通字串,要自己用 os.path.join() 拼、用 os.path.splitext() 拆副檔名,跨平台還得煩惱 Windows 的反斜線和 Unix 的斜線。pathlib(Python 3.4 起內建)把路徑包成物件:用 / 運算子組路徑、用 .name / .stem / .suffix / .parent 直接取各部位,而且自動處理不同作業系統的分隔符。

所以本文一律以 pathlib 當主力,只有在遞迴掃描(os.walk)和「故意覆蓋」(os.replace)這種場景才回頭用 os。這不是新舊之爭,而是「各用所長」,也是把腳本寫得清楚、跨平台不出包的關鍵。


🔙 萬一翻車:救回搞錯的批次操作

批次操作一旦跑錯,影響是成批的。三個情境的處理方式:

廣告

情境一:改名改錯了,想還原

如果你有跑 dry-run 時印出的「舊名 → 新名」對照(建議每次都把它存成一個 .txt),把對照反過來跑一次即可還原。這就是為什麼改名前一定要先留下對照紀錄

情境二:檔案被搬到不知道哪去了

shutil.move 只是搬移、不會刪除,檔案還在,只是進了子資料夾。用檔案總管或 Everything 檔案搜尋神器 打檔名秒搜就能找回;真的亂了,把子資料夾內的檔案再 move 回上層即可。

情境三:檔案被覆蓋(最嚴重)

若在 Unix / macOS 上沒加防覆蓋檢查、被同名檔蓋掉,原檔通常無法直接還原,這也是為什麼步驟三的防覆蓋是硬規則。唯一的保險是動手前先備份,或先在複製出來的測試資料夾上驗證腳本。


💡 總結:把「一次性腳本」變成長期生產力

站長我這幾段腳本在貼上來之前,全部在 Python 3.10 環境(2026-07-03)實際跑過一遍,確認 dry-run、防覆蓋、依副檔名與日期歸檔都如預期,才寫進文章。這也是我建議你養成的習慣:任何會動到檔案的腳本,先在測試資料夾驗證、先 dry-run、再對真資料放行

批次改檔名和整理資料夾只是起點。等你熟了 pathlibglobiterdirshutilmove / copy,同一套邏輯可以延伸到:自動備份、把下載檔依專案歸檔、清掉重複檔、批次轉檔前的整理。腳本自動化真正的價值不是「省這一次的時間」,而是「把你腦中那套整理規則固定下來,以後每次都一致、不出錯」。

至於「該用腳本還是 GUI 工具?」站長的分界是:一次性、規則簡單的改名,用 PowerToys 的 PowerRename 這類圖形工具最快;會重複做、規則複雜、要串接其他步驟的,才值得寫成 Python 腳本。兩個都會,你就能挑最省力的那條路。


❓ 常見問題

Q:一定要裝什麼套件嗎?可以完全用內建模組嗎?

可以。本文用到的 os、pathlib、shutil、datetime 全部是 Python 標準函式庫,裝好 Python 就有,不必 pip install。要處理更複雜的規則(例如讀照片 EXIF 拍攝日期)才需要額外套件。

Q:Path.rename()shutil.move() 差在哪?

rename() 適合「同一個磁碟內」改名或移動,速度快;但跨磁碟(例如從 C 槽搬到 D 槽)可能失敗。shutil.move() 比較聰明,跨磁碟時會自動改用「複製再刪除」,所以搬移檔案建議用 shutil.move()

Q:腳本要怎麼執行?

存成 .py 檔,在終端機打 python 檔名.py 即可。Windows 使用者可以參考站上的 Windows Terminal 完整教學;也可以用 IDLE 或 VS Code 直接按執行。

Q:改名改到一半出錯,前面已經改的會自動還原嗎?

不會。腳本是一個一個檔案循序執行,出錯前已改的不會自動回復。這正是「先 dry-run、先備份、加防覆蓋」的意義,把出錯機率壓到最低。


🔗 延伸閱讀

📎 參考資料來源

📖 第一級|官方文件:

⚠️ 本文核心事實(各函式行為、跨平台覆蓋差異)以 Python 官方文件為準;範例已於 Python 3.10.12 環境實際執行驗證。

📅 本文查證戳記:2026-07-03 依 Python 官方文件撰寫,範例在 Python 3.10 實測通過。若你在新版遇到語法差異,歡迎在留言區回報。

廣告