科技 · 實用指南
在 darktable 中將 JPEG 評等複製給不同資料夾的 RAW
保留依日期整理的 RAW 資料夾與其中的 Jpgs 子資料夾。先檢視轉移計畫,再將明確記錄的星等寫入現有 darktable 旁車檔,最後把變更載入圖庫。

替 JPEG 標上星等,有助於整理大量照片。不過,當對應的 RAW 放在上一層資料夾時,就多了一道工:照片雖然挑好了,準備拿來編修的檔案卻還沒有這些篩選結果。要把評等帶到 RAW,不該非得先重整多年累積的資料夾。
本指南提供適用於這種目錄配置的完整輔助程式。程式會在各日期資料夾內配對,只更新現有 RAW 旁車檔中的一個評等欄位,並保存原始旁車檔。之後仍須讓 darktable 重新讀取變更,才算完成整個流程。請先挑一個較小的日期資料夾,逐一檢查配對並確認結果,再接著處理其餘照片。
1. 讓每組配對留在自己的日期資料夾內
這套流程支援的配置是:RAW 直接存放在日期資料夾中,對應 JPEG 則直接存放在該資料夾的 Jpgs 子資料夾中。例如,Photos/2024/2024-05/Jpgs/DSC01234.JPG 會配對到 Photos/2024/2024-05/DSC01234.ARW。實際接收評等的檔案是 Photos/2024/2024-05/DSC01234.ARW.xmp。
兩者共有的主檔名是 DSC01234,拼字與大小寫都必須一致。另一個月份資料夾中的 DSC01234.ARW 是不同的候選檔,不會拿來補足這裡缺少的配對。輔助程式會走訪你選定的照片目錄樹,但每一組配對都侷限於這個父子目錄關係。它無法判定兩份檔案是否來自同一次拍攝;你必須確認自己的命名方式與資料夾配置確實代表它們是一組。
預設 RAW 副檔名為 ARW,子資料夾名稱為 Jpgs。你可以透過 --raw-ext 設定其他 RAW 副檔名,或用 --jpeg-subdir 指定另一個精確的子目錄名稱。若多張 JPEG 共用主檔名、同時有多種 RAW 格式符合、大小寫造成歧義,或存在疑似編號編修版本的旁車檔,程式會阻擋該項並留待檢查。Jpgs 裡更深一層的資料夾不屬於這項配對規則的範圍。
目標旁車檔必須已經含有 darktable 中繼資料。程式不會建立空白檔案來代替遺失的編修歷史,也不會猜測是否該使用 Lightroom 形式的 DSC01234.xmp。darktable 在匯入時可以讀取其他一些旁車檔命名慣例,但它的原生旁車檔會保留輸入影像的副檔名。這次轉移請使用實際存在的原生旁車檔。
2. 先選定 JPEG 評等的依據
在 darktable 做任何準備之前,先弄清楚想保留的評等目前存放在哪裡。常見情況有三種,準備步驟也不同;程式則提供兩種須明確指定的來源模式。
若評等已內嵌於原始 JPEG,請使用 --rating-source jpeg,並保持這些 JPEG 原樣。不要只是為了準備本指南的來源,就把它們匯入 darktable 或產生 JPEG 旁車檔。程式讀取的是明確記錄的 XMP-xmp:Rating;它不會假定其他應用程式顯示的評等一定已經內嵌在這個欄位。
若想要的評等目前存放在 darktable 資料庫的 JPEG 項目中,請在 lighttable 選取相關 JPEG,再使用 history stack > write sidecar files。這會把目前的資訊寫入 Jpgs/DSC01234.JPG.xmp 這類原生旁車檔。關閉 darktable 後,選擇 --rating-source sidecar。
若現有 JPEG 旁車檔已經記錄了所需評等,就保留這份檔案並以它為準。不要只為了照做上一段,而用較舊的 darktable 資料庫內容覆寫它。旁車檔模式要求檔案位於同一個資料夾,名稱必須精確符合「完整 JPEG 檔名加 .xmp」;程式不會另找省略 JPEG 副檔名的較短同主檔名旁車檔。
只要讀得到,計畫就會同時列出內嵌評等與旁車檔評等。若兩者不一致,警告會顯示差異,最後以你明確選定的來源模式為準;程式不會比較修改時間替你決定。即使另一來源有值,只要選定來源沒有評等,該組就會略過。請選好正確模式並重新建立計畫,不要把缺少資料視為零顆星。
3. 確認 RAW 旁車檔的目前狀態,再關閉 darktable
先確認每份目標旁車檔都代表你打算保留的 RAW 目前編修狀態。如果這些編修保存在 darktable 資料庫中,請在 lighttable 選取本批照片,使用 history stack > write sidecar files;這一步必須先於任何對較舊旁車檔的重新匯入。如果 RAW 旁車檔已經包含所需的較新編修,則應保留它來建立計畫,不要用較舊的資料庫內容覆寫;執行後再將 XMP 讀回資料庫。
對於確實還不在圖庫中的 RAW,請透過 import > add to library 從原有位置加入,接著確認原生旁車檔已寫出。JPEG 中繼資料只需依你選定的來源情況準備。轉移前,先備份重要的圖庫資料與旁車檔;程式稍後產生的備份,只涵蓋它實際修改的 RAW 旁車檔。
離開程式前,開啟 preferences > storage > XMP sidecar files,啟用 look for updated XMP files on startup。這套流程請將 create XMP files 設為 on import,不要設為 never。after edit 原則無法確保每張尚未處理的 RAW 都已經有旁車檔。
關閉 darktable,並在建立、檢查及執行計畫的期間保持關閉。同時暫停其他可能重寫這些檔案的應用程式,讓準備好的狀態維持穩定:影像一旦加入 darktable,資料庫內容就可能優先生效,覆蓋外部對 XMP 所做的變更。

4. 準備 Python、RDFLib 與 ExifTool
你需要 Python 3.10 或更新版本、RDFLib 7.6.0,以及 ExifTool 執行檔。請新建一個可寫入的工作資料夾,存放輔助程式與計畫檔。範例使用 python3;Windows 若以 py -3 執行 Python,後續指令也請統一使用它。
將 RDFLib 安裝到實際執行輔助程式的同一個 Python 環境中。虛擬環境很適合用來與其他專案分開;若採用虛擬環境,請將下文所有指令中的 python3 換成該環境的 Python 執行檔。
python3 -m pip install rdflib==7.6.0
python3 -c "import sys,rdflib; print(sys.version); print(rdflib.__version__)"
從 ExifTool 官方發行管道取得程式,並依其安裝說明設定。在 Windows 上,若要透過命令列使用,請將 exiftool(-k).exe 重新命名為 exiftool.exe,並讓隨附的 exiftool_files 資料夾留在旁邊。若在 macOS 或 Linux 使用可攜式 Perl 發行版,請保留與 exiftool 指令碼放在一起的 lib 目錄,並確認 Perl 可用。
若 ExifTool 已列在 PATH,程式就能以 exiftool 找到它;否則請用 --exiftool 提供執行檔路徑。Windows 可以寫成 --exiftool "C:/Tools/ExifTool/exiftool.exe";macOS 或 Linux 則填入自己執行檔的實際路徑。這個參數接受的是檔案路徑,不是 "perl exiftool" 這類 shell 指令。
建立與執行計畫時,請使用同一個執行檔及版本。如果兩個步驟之間更新或搬移了 ExifTool,請重新建立計畫,讓記錄下來的執行環境與實際一致。
5. 儲存完整輔助程式並檢視原始碼
以下以緊湊的單行套件提供完整輔助程式。請把整段程式碼複製到工作資料夾中的純文字檔,命名為 unpack_rating_helper.py。內容應維持為一個邏輯行;文字編輯器在畫面上自動折行不影響。不要加上引號、Markdown 程式碼圍欄,或文章前後的其他文字。
解包程式全程離線運作。它會解壓縮內含的原始碼、檢查 SHA-256,再以只能新建的方式建立 sync_jpeg_ratings.py,讓你檢視。它不會執行輔助程式,也不會下載任何內容;同名檔案若已存在,就會拒絕覆寫。
import base64,zlib,hashlib,sys; from pathlib import Path; data=zlib.decompress(base64.b64decode('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')); f=Path("sync_jpeg_ratings.py").open("xb") if hashlib.sha256(data).hexdigest()=='ba1136a7f667973bf1fef54682971bf964f4518825c99d45955ed871fdb88158' else sys.exit("SHA-256 mismatch; no helper file written"); f.write(data); f.close(); print("Created sync_jpeg_ratings.py for inspection; it has not been run.")
python3 unpack_rating_helper.py
使用前,請先在文字編輯器開啟產生的 sync_jpeg_ratings.py。還原後的檔案大小為 34,478 位元組,SHA-256 為 ba1136a7f667973bf1fef54682971bf964f4518825c99d45955ed871fdb88158。雜湊值不符時,不會寫出輔助程式;請重新複製原始程式碼段,不要移除檢查。
這份可閱讀的程式只會更動現有 RAW 旁車檔暫存副本中的 XMP-xmp:Rating。它以 RDFLib 比較其餘所有 RDF 中繼資料,因此容許語意相同的 XML 寫法,卻不容許編修資料改變。它不會寫入影像像素、存取 darktable 資料庫,也不會複製 JPEG 的整個 XMP 區塊。
6. 建立計畫,逐一檢視配對
從一個較小的日期資料夾,或選定年份的目錄樹開始。請將指令中的照片路徑與 ExifTool 路徑換成自己的路徑。預設操作只會寫出一份新的 JSON 計畫檔,每張照片及旁車檔都維持原樣。
python3 sync_jpeg_ratings.py "/path/to/Photos/2024" --rating-source sidecar --manifest "ratings-plan.json" --exiftool "/path/to/exiftool"
若要使用 JPEG 的內嵌評等,請把 sidecar 改成 jpeg。需要時可加入 --jpeg-subdir "Jpgs" 或 --raw-ext ARW,並填入合適的值。在 Windows 上,功能相同的完整指令可以像這樣:
py -3 sync_jpeg_ratings.py "D:/Photos/2024" --rating-source sidecar --manifest "ratings-plan.json" --exiftool "C:/Tools/ExifTool/exiftool.exe"
開啟 ratings-plan.json,先看 counts,再逐一檢視每筆 ready 項目的 jpeg、raw、raw_sidecar、rating_source、target_rating 與 new_rating。確認路徑、預期的舊值到新值變化,以及所有內嵌評等與旁車檔評等不一致的警告。試跑成功,不代表每張影像都已準備就緒。
準備就緒的配對才符合執行條件。不需變更的配對已經具有所需的值。略過的配對是因為選定來源沒有明確評等。遭阻擋的配對則需要處理,原因會說明是旁車檔缺少、評等不明、檔名衝突、疑似編修版本,還是其他不支援的情況。請先解決實際問題,再建立新的計畫檔。
計畫會記錄檔案識別資訊、修改時間、完整檔案的雜湊值,以及相關鄰近檔案的名稱。即使完全不編輯像素,計算大型 RAW 的雜湊值仍然需要時間,請挑選大小適中的目錄樹。空白計畫可能只是代表選定資料夾沒有符合條件的 Jpgs 子目錄,不能據此認定整個照片庫都沒有已評等的 JPEG。
7. 分清零顆星、已拒絕與現有評等衝突
來源接受的值是 -1 到 5 之間的整數。零代表真正的零顆星,-1 代表真正的拒絕標記;缺少欄位與這兩種值都不同。選定來源沒有評等時,程式會保留 RAW 原有的評等;遇到無法讀取、小數、超出範圍或有歧義的評等,則會阻擋處理。
預設情況下,有效來源可以填入原本缺少或為零顆星的目標評等;若兩邊的值相同,就不做更動。若目標已有 1–5 顆星或 -1,且來源值不同,現有值會受到保護,即使來源打算將它清成零顆星也一樣。darktable 文件列出的初始匯入評等預設值是 1,所以剛匯入的 RAW 也可能觸發這項保護。
若這次轉移確實應該取代現有值,請先檢視受影響的配對,再使用 --replace-rated 建立另一份計畫。這個設定會套用到新計畫內所有符合條件的衝突;請選擇夠小的目錄樹,不要把它當成只針對某一筆資料的核取方塊。
python3 sync_jpeg_ratings.py "/path/to/Photos/2024" --rating-source sidecar --replace-rated --manifest "ratings-replace-plan.json" --exiftool "/path/to/exiftool"
執行前,再次檢查這份新計畫。不要手動修改 JSON 的值或狀態來強制操作。檢查碼會偵測已檢視計畫中的意外變更,執行時也會核對配對、來源、衝突處理原則與目前檔案。啟用取代選項,仍不能讓無效評等或有歧義的檔案配對通過。
8. 執行確認過的計畫,保留執行紀錄
darktable 仍須保持關閉。執行的必須是剛剛檢查過的那一份計畫;只有你確認的新取代計畫確實是 ratings-replace-plan.json 時,才在這裡使用它。ExifTool 路徑也請維持原來的設定。
python3 sync_jpeg_ratings.py --apply "ratings-plan.json" --exiftool "/path/to/exiftool"
每次寫入之前,程式會重新讀取選定評等,並驗證計畫中記錄的檔案及目錄清單。原始 RAW 旁車檔會保存到計畫檔旁名稱唯一的 rating-sync-backup-<plan-id> 資料夾,且在 sidecars 內保留目標原有的相對資料夾路徑。receipt.json 會記錄每個目標、其備份、舊評等、新評等與雜湊值。
ExifTool 會在暫存旁車檔中變更那一個完整指定的評等欄位。接著,輔助程式會檢查評等與所有非評等的 RDF 資料、再次確認輸入狀態,才替換目標檔案。寫入後還會驗證旁車檔,並確認 RAW、JPEG 與任何已記錄的 JPEG 旁車檔,仍與各自的檔案指紋相符。XML 排版或工具套件識別字可能改變;備份則會保存原始位元組。
檔案變動、相關檔名清單改變,或計畫檔被修改,都會讓已經不符合現況的操作停止。如果一批處理到中途出錯,先前完成的配對仍然完成,後面的配對則尚未嘗試。請查看執行紀錄中的 result_counts 與 unattempted_ready_pairs。這是逐檔提交的流程,並非整批全部成功或全部回復的交易。
請特別留意 committed_verification_failed 與 commit_state_requires_inspection。遇到這些狀態,必須將現有檔案與記錄中的雜湊值比對;替換後發生錯誤,不代表什麼都沒改。如果作業中斷,最後儲存的項目狀態是 prepared,同樣需要檢查。請把計畫、執行紀錄與備份放在一起保存。
名稱唯一的備份目錄會防止直接重複執行同一份計畫。處理完停止的批次後,請為剩餘工作重新建立計畫,不要刪除先前的備份目錄來繞過保護。即使執行紀錄顯示已完成,darktable_reload 仍會標示為待處理。
9. 將旁車檔載入 darktable,確認結果
啟動 darktable。在偵測到旁車檔更新的對話方塊中,選取這次要處理的 RAW 項目,然後選擇 keep the XMP edit,這個操作會把 XMP 內容載入資料庫。不要選 keep the database edit,那會把舊的資料庫狀態寫回旁車檔。上述按鈕文字已在目前的官方原始碼中核對,實際措辭可能隨版本或翻譯而不同。
如果沒有列出預期項目,先不要認定轉移失敗或成功;啟動時的檢查會受到設定與時間戳記影響。可以改用 lighttable 中的 import > add to library:前往原本的 RAW 資料夾,取消勾選 select only new images,並明確選取本批已在圖庫中的 RAW 檔案。該核取方塊控制的是初始選取範圍,單純取消勾選並不等於已選好目標檔案。完成加入操作,才會重新載入它們的 XMP 資料。
請直接使用原位置的檔案。copy & import 採用另一種匯入流程,處理既有旁車檔的方式也不同。這次作業不需要移除或刪除影像。refresh exif 會重新讀取來源影像,可能覆蓋評等;將 JPEG 旁車檔當成 RAW 的歷史堆疊載入,則可能取代編修。這些都不是本次轉移要用的讀回步驟。
檢查 RAW 在畫面上顯示的星等、已拒絕狀態與原有編修,也要確認你仰賴的自訂排序。自訂排序位置不會儲存在 XMP 中,因此保留旁車檔,並不能保證重建所有只存在資料庫中的細節。這些狀態若很重要,就應保留資料庫備份。
若要在繼續編修之前撤銷某一筆已確認的轉移,先關閉 darktable,再從執行紀錄中找出那一組精確的 raw_sidecar 與 backup。以 backup_sha256 驗證備份,並以 new_sidecar_sha256 核對目前的旁車檔。下面這個唯讀指令會輸出檔案的 SHA-256;請依序換成各檔案的實際路徑:
python3 -c "import hashlib,sys; print(hashlib.sha256(open(sys.argv[1],'rb').read()).hexdigest())" "/full/path/to/sidecar.xmp"
如果目前的目標仍符合紀錄中的轉移後版本,就用檔案管理員將那一份原始備份複製回精確對應的 RAW 旁車檔,接著讓 darktable 載入復原後的旁車檔並確認結果。若檔案在執行後又有變動,請先另存一份,檢查後續編修後再決定如何復原。不要動到其他目標。確認這批照片的評等與編修狀態後,再繼續下一個日期資料夾。
驗證範圍:提供的輔助程式使用 Python 3.12、RDFLib 7.6.0,以及 13.59.3 供應方發行套件中的 ExifTool 13.59,通過了 27 個完整 CLI 測試案例。測試使用產生的 JPEG、含有歷史紀錄的合成 darktable 形式 XMP,以及不解析內容的 RAW 佔位檔,檢查了受控的評等變更、影像位元組與非評等中繼資料維持不變、備份、衝突、過時輸入、部分完成,以及明確指定單一目標的復原。解包程式也通過四種還原測試;即使啟用 Python 最佳化,雜湊檢查仍會運作,且不會覆寫既有輸出檔。這些結果不涵蓋 darktable GUI/資料庫讀回、真實相機 RAW 解碼或跨平台執行。介面操作說明已依官方 5.6 手冊與目前原始碼核對;最終結果請在自己的圖庫中確認。