所有入門單元免費開放 · 課程內容持續更新中

讀寫檔案與整理資料夾

學會用 Python 讀寫文字檔、列出資料夾裡的檔案,並寫出一支「先預覽、再執行」的批次改檔名腳本。

第 2.1 堂約 13 分鐘

為什麼從檔案開始?

自動化的第一步,幾乎都跟檔案有關:整理下載資料夾、把掃描的發票照片改成有規則的名字、把每天的紀錄寫進文字檔。這些事手動做一次不難,但每週做、每次幾十個檔案,就很耗時間,也容易出錯。

如果你上過「Python 第一步」,其實已經寫過讀寫檔案的程式了:記帳小工具裡的 with FILE.open(...) 就是。這堂課把它講完整,再加上「整理資料夾」的能力。

先搞懂「路徑」

路徑就是檔案的地址。有兩種寫法:

  • 絕對路徑:從磁碟最上層開始寫,例如 Windows 的 C:\Users\amy\Documents\notes.txt,或 macOS 的 /Users/amy/Documents/notes.txt。
  • 相對路徑:從「終端機目前所在的資料夾」開始算,例如 notes.txt 或 發票掃描/IMG_0001.jpg。

新手最常遇到的 FileNotFoundError,多半是因為終端機站的位置和你以為的不一樣。還記得「Python 第一步」說過的嗎?用 VS Code 開啟資料夾,再用內建終端機執行,就不容易出錯。

讀寫文字檔

with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("今天要繳電話費\n")

with open("notes.txt", "a", encoding="utf-8") as f:
    f.write("記得買牛奶\n")

with open("notes.txt", encoding="utf-8") as f:
    for line in f:
        print(line.strip())
今天要繳電話費
記得買牛奶

with 會在縮排裡的程式跑完後自動關檔。.strip() 把每行頭尾的換行和空白去掉,印出來才不會多空一行。

第二個參數是開檔模式,選錯了後果差很多:

比較圖:r 模式只讀取不改內容;w 模式先清空再寫入,舊內容會消失;a 模式把新內容接在最後面

w 會先把檔案清空。想「追加」一行,要用 a。

用 pathlib 處理資料夾

pathlib 是 Python 內建的工具,用 Path 物件代表一個路徑。它的好處是同一份程式在 Windows 和 macOS 上都能跑,不用煩惱斜線方向。

from pathlib import Path

folder = Path("發票掃描")
print(folder.exists())

for p in folder.glob("*.jpg"):
    print(p.name, p.suffix, p.stat().st_size)

backup = Path("備份")
backup.mkdir(exist_ok=True)
print(backup / "2026-11.txt")
寫法 用途
folder.glob("*.jpg") 找出資料夾裡所有 jpg 檔,* 代表「任何名字」
p.name、p.stem、p.suffix 完整檔名、不含副檔名的名字、副檔名
folder / "a.txt" 組合路徑,自動用對的斜線
mkdir(exist_ok=True) 建立資料夾,已經存在也不會報錯
p.rename(new_path) 改名或搬移檔案

實戰:批次改檔名

情境:你用手機掃描了一疊發票,檔名是 IMG_0001.jpg、IMG_0002.jpg……想改成 2026-11_發票_001.jpg 這種一看就懂的名字。

第一步:做一份假資料來練習

不要直接拿真的照片來試。 先用程式產生幾個假檔案:

from pathlib import Path

folder = Path("發票掃描")
folder.mkdir(exist_ok=True)
for n in range(1, 6):
    (folder / f"IMG_{n:04d}.jpg").write_text("測試用", encoding="utf-8")

f"IMG_{n:04d}.jpg" 裡的 :04d 是「補零到 4 位數」,所以 1 會變成 0001。

第二步:先預覽,確認沒問題再執行

from pathlib import Path

folder = Path("發票掃描")
DRY_RUN = True  # True=只預覽;確認沒問題後才改成 False

files = sorted(folder.glob("IMG_*.jpg"))
for i, old in enumerate(files, start=1):
    new = old.with_name(f"2026-11_發票_{i:03d}.jpg")
    if new.exists():
        print(f"跳過:{new.name} 已經存在")
        continue
    print(f"{old.name}  →  {new.name}")
    if not DRY_RUN:
        old.rename(new)
IMG_0001.jpg  →  2026-11_發票_001.jpg
IMG_0002.jpg  →  2026-11_發票_002.jpg
IMG_0003.jpg  →  2026-11_發票_003.jpg
IMG_0004.jpg  →  2026-11_發票_004.jpg
IMG_0005.jpg  →  2026-11_發票_005.jpg

幾個重點:

  • enumerate(files, start=1) 同時給你「第幾個」和「那個檔案」,從 1 開始數。
  • sorted() 讓順序固定,不然每次跑的順序可能不同。
  • with_name() 保留原本的資料夾,只換檔名。
  • 檢查 new.exists() 是為了不覆蓋到已有的檔案。在 macOS 和 Linux 上,rename 遇到同名檔案會直接覆蓋、不會警告(Windows 則會報錯)。continue 會跳過這一圈,直接處理下一個。

改名前後的資料夾示意圖:左邊是 IMG_0001 到 IMG_0005,經過 DRY_RUN 預覽確認後,右邊變成 2026-11_發票_001 到 005

確認預覽的結果正確,把 DRY_RUN 改成 False 再跑一次,檔案才會真的改名。

讓 AI 幫你寫,但要求它加上安全機制

批次處理檔案的腳本,AI 寫得又快又好。差別在於你會不會要求它「安全地」寫。

可以這樣問 Claude

請幫我寫一支 Python 腳本,用 pathlib 把「下載」資料夾裡的檔案依副檔名分類,移到對應的子資料夾(例如 pdf、jpg、xlsx)。要求:

  1. 最上面有 DRY_RUN 開關,預設 True,只印出「會怎麼搬」,不真的搬。
  2. 目標位置已有同名檔案時跳過,並印出提醒。
  3. 不要刪除任何檔案。
  4. 每一段加上中文註解,我是初學者。

拿到程式後,先讀過一遍,找到 DRY_RUN 和「同名就跳過」的那幾行,確認 AI 真的有照做。

行動練習
  1. 用「第一步」的程式產生 5 個假的 IMG_ 檔案。
  2. 執行改名腳本,先看預覽,再改成 DRY_RUN = False 真的改名。
  3. 把腳本再跑一次,觀察會發生什麼事。(提示:glob("IMG_*.jpg") 還找得到檔案嗎?)
  4. 加分題:每次改名時,用 "a" 模式把「舊檔名 → 新檔名」寫進 rename_log.txt,留下紀錄。

讀完了嗎?

標記完成後,單元與專案的進度會自動更新(只存在這台裝置的瀏覽器)。

卡住了?讓 AI 當你的家教複製這段提問範本,貼到 Claude 或其他 AI 工具,再補上你卡住的地方。

留言與討論

卡關了、有心得,或發現內容需要更新?都歡迎留言。留言使用 GitHub 帳號登入。

留言區即將開放。現在可以先到 GitHub 討論區 發問,或看看 交流頁 的其他管道。