<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Python &#8211; 小豬日常</title>
	<atom:link href="https://piglife.tw/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>https://piglife.tw</link>
	<description>Hello World，一個紀錄生活與學習的地方</description>
	<lastBuildDate>Wed, 10 Dec 2025 16:05:44 +0000</lastBuildDate>
	<language>zh-TW</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>

<image>
	<url>https://piglife.tw/wp-content/uploads/2017/10/cropped-logo-1-32x32.png</url>
	<title>Python &#8211; 小豬日常</title>
	<link>https://piglife.tw</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>使用 Python 批量修正 PDF Metadata Title 為檔名</title>
		<link>https://piglife.tw/technical-notes/python-pdf-metadata-title-fix/</link>
					<comments>https://piglife.tw/technical-notes/python-pdf-metadata-title-fix/#respond</comments>
		
		<dc:creator><![CDATA[小豬]]></dc:creator>
		<pubDate>Wed, 10 Dec 2025 10:25:48 +0000</pubDate>
				<category><![CDATA[技術筆記]]></category>
		<category><![CDATA[PDF Metadata]]></category>
		<category><![CDATA[pypdf]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://piglife.tw/technical-notes/python-pdf-metadata-title-fix/</guid>

					<description><![CDATA[介紹如何使用純 Python 的 pypdf 套件批量修改 PDF 檔案的 Metadata Tit...]]></description>
										<content:encoded><![CDATA[<h2 class="wp-block-heading">前言</h2>
<p>在處理大量 PDF 文件時，常會遇到檔案內嵌的 Metadata Title 與實際檔名不符的問題，這會影響文件管理與搜尋效率。本文示範如何利用純 Python 的 pypdf 套件，自動走訪指定資料夾（含子資料夾）內所有 PDF，將其 Metadata 中的 Title 欄位批量更新為檔名（不含副檔名），同時保留其他 Metadata，並備份原始檔案。適合需要批量整理 PDF 檔案屬性的工程師與自學者。</p>
<h2 class="wp-block-heading">使用 pypdf 讀寫 PDF Metadata</h2>
<p>pypdf 是一個純 Python 的 PDF 操作套件，能讀取與修改 PDF 的內容與屬性。本文重點在修改 PDF 的 Metadata，特別是 /Title 欄位。</p>
<h3 class="wp-block-heading">讀取與複製 PDF 頁面</h3>
<p>為了保留 PDF 內容，先使用 PdfReader 讀取原始 PDF，再用 PdfWriter 複製所有頁面：</p>
<pre><code class="lang-python language-python python">reader = PdfReader(str(src_for_edit))
writer = PdfWriter()
for page in reader.pages:
    writer.add_page(page)</code></pre>
<p>這樣做是為了在不破壞內容的前提下，更新 Metadata。</p>
<h3 class="wp-block-heading">修改 Metadata 中的 Title</h3>
<p>原始 Metadata 透過 reader.metadata 取得，是一個字典。為避免遺失其他欄位，先複製除了 /Title 以外的欄位，並將值轉成字串：</p>
<pre><code class="lang-python language-python python">orig_meta = reader.metadata or {}
new_meta = {}
for key, value in orig_meta.items():
    if key == &quot;/Title&quot;:
        continue
    if value is None:
        continue
    new_meta[key] = str(value)</code></pre>
<p>接著設定新的 Title 為檔名（不含副檔名）：</p>
<pre><code class="lang-python language-python python">new_meta[&quot;/Title&quot;] = pdf_path.stem
writer.add_metadata(new_meta)</code></pre>
<p>這樣可以確保只改 Title，其他 Metadata 保持不變。</p>
<h2 class="wp-block-heading">備份原始檔案與覆寫</h2>
<p>為防止資料遺失，程式會先建立備份檔案（檔名加上 .bak），如果備份已存在，則直接使用原檔：</p>
<pre><code class="lang-python language-python python">backup_path = pdf_path.with_suffix(pdf_path.suffix + &quot;.bak&quot;)
if not backup_path.exists():
    shutil.copy2(pdf_path, backup_path)
    src_for_edit = backup_path
else:
    src_for_edit = pdf_path</code></pre>
<p>最後將修改後的 PDF 直接覆寫原始檔案。</p>
<h2 class="wp-block-heading">遞迴走訪資料夾</h2>
<p>利用 pathlib 的 rglob 方法，可以遞迴搜尋指定資料夾底下所有 .pdf 檔案，並過濾掉備份檔：</p>
<pre><code class="lang-python language-python python">for path in root.rglob(&quot;*.pdf&quot;):
    if path.name.endswith(&quot;.pdf.bak&quot;):
        continue
    fix_pdf_title(path)</code></pre>
<h2 class="wp-block-heading">實際應用與延伸</h2>
<p>此工具適合用於資料整理、文件管理系統，或是需要統一 PDF Metadata 的場景。未來可擴充功能，例如修改其他 Metadata 欄位、支援多種檔案格式，或加入多線程提升處理效率。</p>
<h2 class="wp-block-heading">常見問題與注意事項</h2>
<ul>
<li>確保執行環境有安裝 pypdf 套件。</li>
<li>備份機制避免資料遺失，但仍建議先手動備份重要檔案。</li>
<li>修改 Metadata 不會改變 PDF 內容，但部分 PDF 可能因加密或損毀導致處理失敗。</li>
</ul>
<h2 class="wp-block-heading">完整程式碼</h2>
<pre><code class="lang-python language-python python">#!/usr/bin/env python3
# -*- coding: utf-8 -*-

&quot;&quot;&quot;
批量修正 PDF Metadata Title（使用 pypdf，純 Python，不需編譯）

功能：
- 走訪指定資料夾（含子資料夾）所有 .pdf
- 把 PDF 內嵌的 /Title 改成「檔名（不含 .pdf）」
- 原檔先備份成 xxx.pdf.bak
&quot;&quot;&quot;

import sys
from pathlib import Path
import shutil

from pypdf import PdfReader, PdfWriter

def fix_pdf_title(pdf_path: Path):
    &quot;&quot;&quot;把單一 PDF 的 Title 改成檔名（不含副檔名）&quot;&quot;&quot;
    try:
        print(f&quot;處理：{pdf_path}&quot;)

        # 建立備份：xxx.pdf.bak（如果已存在就略過）
        backup_path = pdf_path.with_suffix(pdf_path.suffix + &quot;.bak&quot;)
        if not backup_path.exists():
            shutil.copy2(pdf_path, backup_path)
            src_for_edit = backup_path  # 從備份讀
        else:
            src_for_edit = pdf_path     # 已備份過就直接用目前檔案

        # 讀 PDF
        reader = PdfReader(str(src_for_edit))
        writer = PdfWriter()

        # 複製所有頁
        for page in reader.pages:
            writer.add_page(page)

        # 讀取原有 metadata
        orig_meta = reader.metadata or {}
        new_meta = {}

        # 保留其他欄位，只改 /Title
        for key, value in orig_meta.items():
            if key == &quot;/Title&quot;:
                continue
            if value is None:
                continue
            new_meta[key] = str(value)

        # 設定新的 Title = 檔名（不含 .pdf）
        new_title = pdf_path.stem
        new_meta[&quot;/Title&quot;] = new_title

        writer.add_metadata(new_meta)

        # 寫回原本檔名（覆蓋）
        with open(pdf_path, &quot;wb&quot;) as f_out:
            writer.write(f_out)

        print(f&quot;  ✅ 已更新 Title 為：{new_title}\n&quot;)

    except Exception as e:
        print(f&quot;  ❌ 發生錯誤：{e}\n&quot;)

def scan_folder(root: Path):
    &quot;&quot;&quot;走訪資料夾底下所有 .pdf&quot;&quot;&quot;
    for path in root.rglob(&quot;*.pdf&quot;):
        # 跳過備份檔
        if path.name.endswith(&quot;.pdf.bak&quot;):
            continue
        fix_pdf_title(path)

def main():
    if len(sys.argv) &gt;= 2:
        target_dir = Path(sys.argv[1]).expanduser().resolve()
    else:
        # 沒帶參數就用目前工作目錄
        target_dir = Path.cwd()

    if not target_dir.exists() or not target_dir.is_dir():
        print(f&quot;找不到資料夾：{target_dir}&quot;)
        sys.exit(1)

    print(f&quot;開始處理資料夾：{target_dir}\n&quot;)
    scan_folder(target_dir)
    print(&quot;全部處理完成 🎉&quot;)

if __name__ == &quot;__main__&quot;:
    main()</code></pre>]]></content:encoded>
					
					<wfw:commentRss>https://piglife.tw/technical-notes/python-pdf-metadata-title-fix/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
