製作照片的縮圖目錄

每個愛好拍照者都有的苦惱,就是想找到過去拍過的某一張照片。硬碟裡幾千幾百張照片,就算神仙也記不得。這時,縮圖目錄就能派上用場了。

你還記得多年前拍過的照片嗎?就算記得,知道是哪一天拍的嗎?

可以製作縮圖目錄 (contact sheet) 的工具很多,Photoshop 和 Canon DPP 都可以辦到。不過痛苦的地方是,我的照片都是按照拍攝日期歸檔在資料夾裡,想要製作某年份的縮圖目錄,還得一個個地把上百個資料夾下的幾千張照片都加到軟體裡。這一回,試試看用 Claude 來簡化這個步驟。

Claude 建議安裝免費工具,不過我不太喜歡,還是偏好用手上的 DPP 或 Photoshop 解決

原本使用 Canon DPP 時,方法是建立新的相片集 (collection),然後依序將該年份的照片全都新增到相片集中。最後按照拍攝日期/時間排序好,再透過列印到 PDF 的方式產生該年份的縮圖目錄。最終,我可以得到一個有著許多頁照片縮圖的 PDF。這 PDF 不但我自己愛用,Esther 也喜歡,甚至放到手機裡。

原先,我都是在 Canon DPP 中建立 Collection,然後逐個資料夾將照片加到 Collection 中
辛苦了個大半天,總算將 4 千多張照片加到同一個 Collection,再列印成 PDF 的縮圖目錄

問了問 Claude,由於 Canon 沒有開放 DPP 的 API,所以外部程式無法直接在 DPP 中新增 collection 並放入照片。替代的方式是,可以新增一個資料夾,然後在 Windows 裡放入所有照片資料夾中的照片捷徑,然後就從 DPP 裡開啟這個資料夾並製作縮圖目錄就好。這種方式只需要使用 Powershell,方便多了。

DPP 沒有公開 API,所以 Claude 無法從外界新增 Collection
Claude 給了兩個方案。兩個方案講的是同一件事:不要用 Collection,而是建立一個暫存資料夾
測試一下暫存資料夾的作法。Claude 建立了一個存放所有照片捷徑的暫存資料夾

測試了一下,Canon DPP 並無法正確辨識 Windows 捷徑 (.lnk),但可以讀取符號連結 (symbolic link)。符號連結是在檔案系統層級的功能,連結會被視為 CR3 檔案本身。

結果 Canon DPP 無法正確識別捷徑。Claude 改用檔案系統層級的符號連結
設計成可以指定年份
覺得不夠好,再改成執行時程式會先詢問年份的版本

就此,整個動作簡單了起來。Claude 產生了兩支檔案,分別是 Powershell 指令的 Make-SymlinkFolder.ps1 檔案,以及直接執行 .ps1 檔案的 Make-SymlinkFolder.bat 批次檔。我執行批次檔,讓程式在桌面新增了 DPP_Test_2025 資料夾,裡面放入硬碟中 2025 年所有資料夾下的所有照片,總數是 3400 多張。

以系統管理員身分執行批次檔 (製作符號連結需要系統管理員身分)。程式會先詢問要處理的年份
程式建立暫存資料夾,接著為 2025 年資料夾下的所有照片檔案建立符號連結
大概 10 秒鐘左右,程式就在桌面上建立了 “DPP_Test_2025” 暫存資料夾,底下有 3498 張照片的符號連結
符號連結的每個檔案大小都是 0 KB,真的只是原檔的參照

接著啟動 Canon DPP,瀏覽到這個資料夾,全選後按照拍照日期排序,如往常般列印成 PDF 即可。我起碼可以省下上百次選取照片並加入到 collection 的動作。

進入 Canon DPP,瀏覽 “DPP_Test_2025” 這個資料夾,裡面會顯示 3 千多張照片 (但照片實際位置還是在原本的 2025\2025-xx-xx\ 下)
選擇列印到 contact sheet
在對話方塊中,選擇印表機為可以列印成 PDF 的「Micorosft Print to PDF」
列印完成的縮圖目錄 PDF。有了這個,很快就可以翻閱到想找的照片
每年做一份縮圖目錄。也可以放進手機,當成生活的縮影

Make-SymlinkFolder.ps1

<#
.SYNOPSIS
    在暫存資料夾中,建立指定年份資料夾下所有 .CR3 檔案的符號連結,方便在 Canon DPP 中測試瀏覽/Collection 功能。

.DESCRIPTION
    - 掃描指定的年份資料夾 (例如 D:\Family\2026) 底下所有 yyyy-MM-dd 日期子資料夾
    - 找出所有 .CR3 檔案
    - 在暫存資料夾中為每個檔案建立符號連結 (symbolic link),檔名會加上日期前綴
      (例如 2026-08-28_IMG_0001.CR3),避免不同天但同檔名的照片互相覆蓋
    - 符號連結本身幾乎不佔空間,只是指向原始檔案的連結,不會複製或搬動照片,
      但在檔案系統層級會直接呈現為 .CR3 檔案,一般程式 (包含 DPP) 應該能正常讀取

.NOTES
    重要:建立符號連結需要系統管理員權限!
        請用「以系統管理員身分執行」開啟 PowerShell 或對應的批次檔,
        否則會出現「您沒有此作業所需的權限」之類的錯誤。

    使用方式:
        .\Make-SymlinkFolder.ps1 -YearFolder "D:\Family\2026"

        指定暫存資料夾位置 (預設在桌面上建立 DPP_Test_<年份> 資料夾):
        .\Make-SymlinkFolder.ps1 -YearFolder "D:\Family\2026" -DestFolder "D:\DPP_Test"
#>

param(
    [Parameter(Mandatory = $true)]
    [string]$YearFolder,
    [string]$DestFolder = ""
)

# 檢查是否為系統管理員權限執行
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
$isAdmin = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

if (-not $isAdmin) {
    Write-Error "建立符號連結需要系統管理員權限,請以「系統管理員身分執行」重新開啟 PowerShell 或批次檔再試一次。"
    exit 1
}

if (-not (Test-Path $YearFolder)) {
    Write-Error "找不到資料夾 $YearFolder,請確認路徑是否正確。"
    exit 1
}

if ([string]::IsNullOrWhiteSpace($DestFolder)) {
    $yearName = Split-Path $YearFolder -Leaf
    $DestFolder = Join-Path ([Environment]::GetFolderPath("Desktop")) "DPP_Test_$yearName"
}

# 清空暫存資料夾內舊的符號連結,確保每次執行結果是最新的
# (只刪除 .CR3 符號連結本身,不會動到連結指向的原始照片)
if (Test-Path $DestFolder) {
    Get-ChildItem -Path $DestFolder -Filter "*.CR3" -File | ForEach-Object {
        if ($_.LinkType -eq "SymbolicLink") {
            Remove-Item -Path $_.FullName -Force
        }
    }
} else {
    New-Item -ItemType Directory -Path $DestFolder -Force | Out-Null
}

Write-Host "正在掃描 $YearFolder 底下所有 .CR3 檔案..."
$cr3Files = Get-ChildItem -Path $YearFolder -Recurse -Filter "*.cr3" -File

if ($cr3Files.Count -eq 0) {
    Write-Host "找不到任何 .cr3 檔案。"
    exit 0
}

Write-Host "共找到 $($cr3Files.Count) 個檔案,開始建立符號連結..."

$counter = 0
$failCount = 0

foreach ($file in $cr3Files) {
    $dateFolderName = $file.Directory.Name   # 例如 "2026-08-28"
    $linkName = "${dateFolderName}_$($file.Name)"
    $linkPath = Join-Path $DestFolder $linkName

    # 避免極少數同名衝突,加上流水號
    $i = 1
    while (Test-Path $linkPath) {
        $linkName = "${dateFolderName}_$($file.BaseName)_$i$($file.Extension)"
        $linkPath = Join-Path $DestFolder $linkName
        $i++
    }

    try {
        New-Item -ItemType SymbolicLink -Path $linkPath -Target $file.FullName -ErrorAction Stop | Out-Null
        $counter++
    }
    catch {
        Write-Warning "建立符號連結失敗:$($file.FullName) -> $($_.Exception.Message)"
        $failCount++
    }

    Write-Progress -Activity "建立符號連結中" -Status "$($counter + $failCount) / $($cr3Files.Count)" -PercentComplete ((($counter + $failCount) / $cr3Files.Count) * 100)
}

Write-Host "完成!成功建立 $counter 個符號連結於:$DestFolder"
if ($failCount -gt 0) {
    Write-Host "有 $failCount 個檔案建立失敗,請確認上方警告訊息。"
}

Make-SymlinkFolder.bat

@echo off
REM ============================================================
REM  Create symbolic links for all CR3 files under a year folder
REM  This MUST run as Administrator (symbolic links require it)
REM  Edit FAMILY_ROOT and SCRIPT_PATH below if paths are different
REM ============================================================

set SCRIPT_PATH=E:\Make-SymlinkFolder.ps1
set FAMILY_ROOT=D:\Family

set /p YEAR=Please enter the year (e.g. 2025):

if "%YEAR%"=="" (
    echo No year entered. Exiting.
    pause >nul
    exit /b 1
)

set YEAR_FOLDER=%FAMILY_ROOT%\%YEAR%

echo.
echo Target folder: %YEAR_FOLDER%
echo.

powershell -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_PATH%" -YearFolder "%YEAR_FOLDER%"

echo.
echo ============================================================
echo Done. Please check above for any error messages.
echo This window will not close automatically - press any key.
echo ============================================================
pause >nul

Leave a Reply

Your email address will not be published. Required fields are marked *