يوفر OsxPhotos القدرة على التفاعل مع صور Apple والاستعلام عنها على MacOS و Linux. يمكنك الاستعلام عن قاعدة بيانات مكتبة الصور - على سبيل المثال ، اسم الملف ومسار الملف والبيانات الوصفية مثل الكلمات/العلامات الرئيسية والأشخاص/الوجوه والألبومات ، إلخ ، يمكنك أيضًا تصدير كل من الصور الأصلية والمتحركة. يعمل Osxphotos أيضًا مع مكتبات Iphoto على الرغم من أن بعض الميزات متوفرة فقط للصور.

تم اختباره على Ubuntu Linux و MacOS. العديد من الميزات متوفرة فقط على MacOS.
على Linux ، لن تتوفر ميزات MacOS الخاصة بـ CLI (لن يتم عرضها في إخراج المساعدة). ستعمل أوامر التصدير والاستعلام CLI وكذلك API Python على Linux والتي تمكنك من تصدير الصور من مكتبة صور على جهاز Linux.
تم اختباره على Macos Sierra (10.12.6) من خلال Macos Sonoma (14.1). تم اختباره على كل من X86 وسيليكون Apple (M1).
تم اختبار OSXPHOTOS إلى الحد الأدنى مع MACOS Sequoia (15 بيتا) ولكن إصدارات بيتا الجديدة قد تحطم دعم OSXPHOTOS. إذا واجهت مشاكل مع MacOS 15.0 ، يرجى فتح مشكلة.
| نسخة ماكوس | اسم ماكوس | إصدار photos.app |
|---|---|---|
| 15.0 | سيكويا | 10.0 (دعم بيتا) |
| 14.0 - 14.6 | سونوما | 9.0 ✅ |
| 13.0 - 13.6 | فينتورا | 8.0 ✅ |
| 12.0 - 12.7 | مونتيري | 7.0 ✅ |
| 10.16 ، 11.0-11.7 | كبير السور | 6.0 ✅ |
| 10.15.1 - 10.15.7 | كاتالينا | 5.0 ✅ |
| 10.14.5 ، 10.14.6 | موهافي | 4.0 ✅ |
| 10.13.6 | هاي سييرا | 3.0 ✅ |
| 10.12.6 | سييرا | 2.0 ✅ |
يتم توفير الدعم المحدود أيضًا لتصدير الصور والبيانات الوصفية من مكتبات Iphoto. تم اختبار Iphoto 9.6.1 فقط (الإصدار النهائي).
ستقرأ هذه الحزمة قواعد بيانات الصور لأي إصدار مدعوم على أي إصدار مدعوم من MacOS. على سبيل المثال ، يمكنك قراءة قاعدة بيانات تم إنشاؤها باستخدام الصور 5.0 على MacOS 10.15 على جهاز يعمل MacOS 10.12 والعكس بالعكس.
يتطلب python> = 3.10 ، <= 3.13 .
بالنسبة إلى MacOS 15.0 / Sequoia Developer Preview ، يتم توفير دعم Alpha (أولي للغاية ، غير مضمون للعمل). لم يتم اختبار جميع ميزات Osxphotos وقد لا تعمل بعض الميزات. إذا واجهت مشكلات ، يرجى فتح مشكلة على Github.
الطريقة الموصى بها لتثبيت osxphotos هي عبر أداة MANGER UV Python.
uvTerminal (ابحث عن Terminal في دائرة الضوء أو البحث في Applications/Utilities )uv عن طريق تشغيل الأمر التالي في Terminal: curl -LsSf https://astral.sh/uv/install.sh | sh إذا قمت بتثبيت uv مسبقًا ، فقم بالترقية إلى أحدث إصدار:
uv self updateuv tool install --python 3.12 osxphotososxphotos عن طريق الكتابة: osxphotos بمجرد تثبيت OsxPhotos مع uv ، للترقية إلى أحدث إصدار:
uv tool upgrade osxphotos إذا كنت ترغب في تجربة osxphotos دون تثبيته ، فيمكنك تشغيل uv tool run --python 3.12 osxphotos أو uvx --python 3.12 osxphotos .
يمكنك تثبيت osxphotos مباشرة من PYPI:
python3 -m pip install osxphotos
بمجرد تثبيت OsxPhotos مع PIP ، للترقية إلى أحدث إصدار:
python3 -m pip install --upgrade osxphotos
إذا كنت تستخدم Macports Package Manager على جهاز Mac:
sudo port install osxphotos
قد تتسبب واحدة على الأقل من حزم بيثون المحددة في نظام Linux على خطأ في Linux قد تتسبب في خطأ أثناء التثبيت باستخدام pip أو pipx . إذا واجهت خطأً مشابهًا لـ: pip._vendor.packaging.version.InvalidVersion: Invalid version: '6.5.0-1022-generic ، يجب أن تتمكن من تثبيت Osxphotos عن طريق إنشاء وتفعيل بيئة افتراضية:
python3 -m venv .venv-osxphotos
source .venv-osxphotos/bin/activate
python3 -m pip install osxphotos لاستخدام OSXPHOTOS ، ستحتاج إلى التأكد من تنشيط VENV باستخدام source .venv-osxphotos/bin/activate .
يمكنك تسمية البيئة الافتراضية أي شيء تريده ؛ يتم استخدام .venv-osxphotos في هذا المثال لتوضيح أن البيئة الافتراضية تستخدمها OSXPHOTOS ولتجنب التعارض مع البيئات الافتراضية الأخرى التي ، حسب الاتفاقية ، غالبًا ما تتم تسمية .venv أو venv .
إذا كنت ترغب في العمل على رمز OSXPHOTOS أو المساهمة في المشروع ، فيمكنك التثبيت من مستودع GIT:
git clone https://github.com/RhetTbull/osxphotos.git
cd osxphotos
ملحوظة
يعد repo git لهذا المشروع كبيرًا جدًا (> 3 جيجابايت) لأنه يحتوي على مكتبات صور متعددة تستخدم للاختبار على إصدارات مختلفة من MacOS.
إذا كنت ترغب فقط في استخدام حزمة OSXPHOTOS في الكود الخاص بك ، فإنني أوصيك بتثبيت أحدث إصدار من PYPI والذي لا يتضمن جميع مكتبات الاختبار. إذا كنت ترغب فقط في استخدام الأداة المساعدة لسطر الأوامر ، فيمكنك تنزيل جهاز تنفيذ مسبقًا لأحدث الإصدار أو يمكنك التثبيت عبر pip الذي يقوم أيضًا بتثبيت تطبيق سطر الأوامر. إذا لم تكن مرتاحًا لتشغيل Python على جهاز Mac الخاص بك ، فابدأ مع التنفيذ المبني مسبقًا أو مع uv كما هو موضح أعلاه.
بدلاً من ذلك ، لاستنساخ المستودع بدون بيانات الاختبار:
git clone --filter=blob:none --no-checkout --sparse https://github.com/RhetTbull/osxphotos.git
cd osxphotos
git sparse-checkout set --no-cone '/*' '!tests'
git checkout
بعد ذلك ، قم بتثبيت التبعيات المطلوبة ، و osxphotos نفسها. أوصيك بإنشاء بيئة افتراضية قبل تثبيت OSXPHOTOS.
python3 -m pip install -r dev_requirements.txt
python3 -m pip install -r requirements.txt
python3 -m pip install -e .
بمجرد تثبيت OSXPHOTOS عبر مستودع GIT ، للترقية إلى أحدث إصدار:
cd osxphotos
git pull
python3 -m pip install -e .
انظر أيضًا ملاحظات المطور في readme_dev.md.
يمكنك أيضًا تنزيل قابلة للتنفيذ قابلة للتنفيذ قابلة للبناء مسبقًا-لا تتطلب تثبيت Python-من صفحة الإصدارات. ابحث عن الملف الذي يحمل اسمًا مشابهًا لـ osxphotos_MacOS_exe_darwin_x86_64_v0.63.5.zip . في هذه الحالة ، يحدد v0.63.5 الإصدار 0.63.5 و x86_64 يحدد منصة Intel X86 ؛ يجب عليك تنزيل أحدث إصدار متاح. بالنسبة لسيليكون Apple ، هناك نسخة مكافئة arm64 من القابل للتنفيذ. قم بإلغاء ضغط الملف ووضع osxphotos الثنائي في مسار النظام الخاص بك. حاليًا ، لا يتم توضيح الثنائي ، لذا سيتعين عليك تفويض التطبيق لتشغيله في تفضيلات النظام | إعدادات الأمان والخصوصية. إذا كنت لا تعرف كيفية القيام بذلك ، أوصي باستخدام uv كما هو موضح أعلاه.
راجع الوثائق لمزيد من المعلومات حول استخدام OSXPHOTOS.
تم توثيق Osxphotos جيدًا. انظر البرنامج التعليمي للحصول على وصف للميزات الرئيسية. يمكن الوصول إلى البرنامج التعليمي باستخدام الأمر osxphotos tutorial عبر سطر الأوامر. إذا كنت مهتمًا باستخدام OSXPHOTOS في الكود الخاص بك ، راجع API_README.MD للحصول على وصف لـ API بالإضافة إلى برامج المثال. تتوفر الوثائق الكاملة عبر الإنترنت ويمكن أيضًا الوصول إليها باستخدام osxphotos docs عبر الأمر عبر سطر الأوامر. سيعرض osxphotos help مساعدة في المحطة. يمكنك استخدام osxphotos help COMMAND للحصول على مساعدة في الأمر. على سبيل المثال ، osxphotos help export . للبحث بمساعدة أمر معين ، استخدم osxphotos help COMMAND TOPIC ، على سبيل المثال ، osxphotos help export sidecar .
إذا كانت لديك أسئلة ، فأنت ترغب في عرض المشاريع التي تم إنشاؤها باستخدام OsxPhotos ، أو إذا كنت تريد فقط أن تقول مرحبًا ، فيرجى استخدام منتدى GitHub مناقشات أو Osxphotos subreddit على Reddit.
ستقوم هذه الحزمة بتثبيت أداة سطر الأوامر تسمى osxphotos والتي تتيح لك الاستعلام عن قاعدة بيانات الصور. بدلاً من ذلك ، يمكنك أيضًا تشغيل أداة سطر الأوامر مثل هذا: python3 -m osxphotos
Usage: osxphotos [OPTIONS] COMMAND [ARGS]...
OSXPhotos: the multi-tool for your Photos library.
To get help on a specific command, use "osxphotos COMMAND --help" or
"osxphotos help COMMAND"; for example, "osxphotos help export".
To search help for a specific topic within a command, run "osxphotos help
COMMAND TOPIC"; for example, "osxphotos help export keyword" to get help
related to keywords when using the export command.
To see the full documentation in your browser, run "osxphotos docs".
Some advanced commands are hidden by default. To see all commands, run
"OSXPHOTOS_SHOW_HIDDEN=1 osxphotos help". Some commands also have hidden
options. These can be seen by running "OSXPHOTOS_SHOW_HIDDEN=1 osxphotos help
COMMAND".
Options:
-v, --version Show the version and exit.
-h, --help Show this message and exit.
Commands:
about Print information about osxphotos including license.
add-locations Add missing location data to photos in Photos.app using...
albums Print out albums found in the Photos library.
batch-edit Batch edit photo metadata such as title, description,...
compare Compare two Photos libraries to find differences
docs Open osxphotos documentation in your browser.
dump Print list of all photos & associated info from the Photos...
exiftool Run exiftool on previously exported files to update metadata.
export Export photos from the Photos database.
exportdb Utilities for working with the osxphotos export database
help Print help; for help on commands: help <command>.
import Import photos and videos into Photos.
info Print out descriptive info of the Photos library database.
inspect Interactively inspect photos selected in Photos.
install Install Python packages into the same environment as...
keywords Print out keywords found in the Photos library.
labels Print out image classification labels found in the Photos...
list Print list of Photos libraries found on the system.
orphans Find orphaned photos in a Photos library
persons Print out persons (faces) found in the Photos library.
places Print out places found in the Photos library.
push-exif Write photo metadata to original files in the Photos library
query Query the Photos database using 1 or more search options;...
repl Run interactive osxphotos REPL shell (useful for...
run Run a python file using same environment as osxphotos.
show Show photo, album, or folder in Photos from UUID_OR_NAME
sync Sync metadata and albums between Photos libraries.
template Interactively render templates for selected photo.
theme Manage osxphotos color themes.
timewarp Adjust date/time/timezone of photos in Apple Photos.
tutorial Display osxphotos tutorial.
uninstall Uninstall Python packages from the osxphotos environment
update Update the installation to the latest version.
uuid Print out unique IDs (UUID) of photos selected in Photos
version Check for new version of osxphotos.
للحصول على مساعدة في أمر معين ، استخدم osxphotos help COMMAND ، على سبيل المثال ، osxphotos help export للحصول على مساعدة في أمر export .
بعض الأوامر مثل export query لديها عدد كبير من الخيارات. للبحث عن الخيارات المتعلقة بموضوع محدد ، يمكنك استخدام osxphotos help COMMAND TOPIC . على سبيل المثال ، osxphotos help export raw في العثور على الخيارات المتعلقة بالملفات الأولية (البحث غير حساس للحالة):
Usage: osxphotos export [OPTIONS] ... DEST
Export photos from the Photos database. Export path DEST is required.
Optionally, query the Photos database using 1 or more search options; if
more than one option is provided, they are treated as "AND" (e.g. search for
photos matching all options). If no query options are provided, all photos
will be exported. By default, all versions of all photos will be exported
including edited versions, live photo movies, burst photos, and associated
raw images. See --skip-edited, --skip-live, --skip-bursts, and --skip-raw
options to modify this behavior.
Options that match 'raw':
--has-raw Search for photos with both a jpeg and
raw version
--skip-raw Do not export associated RAW image of a
RAW+JPEG pair. Note: this does not skip RAW
photos if the RAW photo does not have an
associated JPEG image (e.g. the RAW file was
imported to Photos without a JPEG preview).
--convert-to-jpeg Convert all non-JPEG images (e.g. RAW, HEIC,
PNG, etc) to JPEG upon export. Note: does not
convert the RAW component of a RAW+JPEG pair as
the associated JPEG image will be exported. You
can use --skip-raw to skip
exporting the associated RAW image of a
RAW+JPEG pair. See also --jpeg-quality and
--jpeg-ext. Only works if your Mac has a GPU
(thus may not work on virtual machines).
osxphotos export --export-by-date --library ~/Pictures/Photos Library.photoslibrary ~/Desktop/export
osxphotos query --keyword Kids --json --library ~/Pictures/Photos Library.photoslibrary >results.json
osxphotos query --only-movies --min-size 200MB --add-to-album "Big Videos"
فلسفة التصميم الخاصة بـ OSXPHOTOS هي "اجعل الأمور سهلة وجعل الأشياء الصعبة ممكنة". "لجعل الأشياء الصعبة ممكنة" ، يكون Osxphotos مرنًا للغاية ولديه العديد من خيارات التكوين - أمر export على سبيل المثال ، يحتوي على أكثر من 100 خيار لسطر الأوامر. وبالتالي ، قد يبدو Osxphotos شاقة في البداية. الغرض من هذا البرنامج التعليمي هو شرح عدد من حالات الاستخدام الشائعة مع أمثلة ، ونأمل أن تجعل Osxphotos أقل شاقة للاستخدام. يتضمن OSXPHOTOS عدة أوامر لاسترداد المعلومات من مكتبة الصور الخاصة بك ، لكن أكثر المستخدمين المهتمين به هو أمر export الذي يصدر الصور من المكتبة بحيث يكون محور هذا البرنامج التعليمي.
osxphotos export /path/to/export
يقوم هذا الأمر بتصدير جميع صورك إلى دليل /path/to/export .
ملاحظة : يستخدم OsxPhotos مصطلح "صورة" للإشارة إلى أصول الوسائط العامة في مكتبة الصور الخاصة بك. قد تكون الصورة صورة ، ملف فيديو ، مزيج من ملفات الصور والفيديو الثابتة (على سبيل المثال ، Apple "Live Photo" وهي صورة فيديو Live Apple وهي صورة معاينة LIVE) ، صورة JPEG مع صورة RAW المرتبطة ، إلخ.
على الرغم من أن الأمر السابق سيقوم بتصدير جميع صورك (ومقاطع الفيديو-انظر الملاحظة أعلاه) ، فربما لا تفعل ما تريده بالضبط. في المثال السابق ، سيتم تصدير جميع الصور إلى مجلد واحد: /path/to/export . إذا كان لديك مكتبة كبيرة مع الآلاف من الصور ومقاطع الفيديو ، فهذا على الأرجح ليس مفيدًا للغاية. يمكنك استخدام الخيار --export-by-date لتصدير الصور إلى هيكل مجلد تم تنظيمه حسب السنة والشهر واليوم ، على سبيل المثال 2021/04/21 :
osxphotos export /path/to/export --export-by-date
مع هذا الأمر ، سيتم تصدير الصورة التي تم إنشاؤها في 31 مايو 2015 إلى: /path/to/export/2015/05/31
إذا كنت تفضل بنية دليل مختلفة لصورك المصدرة ، فإن OsxPhotos يوفر نظام قالب مرن للغاية يسمح لك بتحديد بنية الدليل باستخدام خيار --directory . على سبيل المثال ، تم تصدير هذا الأمر إلى هيكل دليل يشبه: 2015/May (اسم السنة / الشهر المكون من 4 أرقام):
osxphotos export /path/to/export --directory "{created.year}/{created.month}"
السلسلة التالية --directory هي osxphotos template string . تستخدم سلاسل القوالب على نطاق واسع في جميع أنحاء Osxphotos ويستحق وقتك لمعرفة المزيد عنها. في سلسلة قالب ، يتم استبدال القيم بين الأقواس {created.year} ، على سبيل المثال. في هذه الحالة ، {created.year} هي السنة المكونة من 4 أرقام لتاريخ إنشاء الصورة و {created.month} هي اسم الشهر الكامل في لغة المستخدم (على سبيل المثال ، May ، mai ، إلخ). في نظام قالب OSXPHOTOS ، يشار إليها باسم حقول القالب. يتم تفسير النص غير المدرج بين أزواج {} حرفيًا ، في هذه الحالة / ، هو فاصل دليل.
يوفر OsxPhotos الوصول إلى جميع البيانات الوصفية المعروفة للصور حول صورك تقريبًا. على سبيل المثال ، تقوم الصور بإجراء بحث عكسي على الصور على الصور التي تحتوي على إحداثيات GPS لتعيين أسماء الأماكن إلى الصورة. باستخدام قالب --directory ، يمكنك بالتالي تصدير الصور التي تم تنظيمها باسم البلد:
osxphotos export /path/to/export --directory "{created.year}/{place.name.country}"
بالطبع ، قد لا يكون لبعض الصور اسم المكان المرتبط به ، لذا يتيح لك نظام القالب تحديد قيمة افتراضية لاستخدامها إذا كان حقل قالب فارغًا (ليس له قيمة).
osxphotos export /path/to/export --directory "{created.year}/{place.name.country,No-Country}"
القيمة بعد "، في سلسلة القالب هي القيمة الافتراضية ، في هذه الحالة" بدون دولة ". ملاحظة : إذا لم تقم بتحديد قيمة افتراضية وكان حقل قالب فارغًا ، فسيستخدم OSXPHOTOS "_" (الحرف السفلي) باعتباره الافتراضي.
قد تتوسع بعض حقول القالب ، مثل {keyword} ، إلى أكثر من قيمة واحدة. على سبيل المثال ، إذا كانت الصورة تحتوي على كلمات رئيسية لـ "Travel" و "Vacation" ، فسيتم توسيع {keyword} إلى "Travel" ، "Facail". عند استخدامها مع --directory ، فإن هذا سيؤدي إلى تصدير الصورة إلى أكثر من دليل واحد (وبالتالي سيتم تصدير أكثر من نسخة واحدة من الصورة). على سبيل المثال ، إذا كان IMG_1234.JPG يحتوي على كلمات رئيسية Travel ، Vacation وتدير الأمر التالي:
osxphotos export /path/to/export --directory "{keyword}"
ستكون الملفات المصدرة:
/path/to/export/Travel/IMG_1234.JPG
/path/to/export/Vacation/IMG_1234.JPG
إذا تم تنظيم صورك في المجلدات والألبومات في الصور ، فيمكنك الحفاظ على هذا الهيكل على التصدير باستخدام حقل قالب {folder_album} مع خيار --directory . على سبيل المثال ، إذا كان لديك صورة في Vacation الألبوم التي توجد في مجلد Travel ، فإن الأمر التالي سيصدر الصورة إلى دليل Travel/Vacation :
osxphotos export /path/to/export --directory "{folder_album}"
يمكن أن تنتمي الصور إلى أكثر من ألبوم واحد. في هذه الحالة ، سيتوسع حقل القالب {folder_album} إلى جميع أسماء الألبوم التي تنتمي إليها الصورة. على سبيل المثال ، إذا كانت الصورة تنتمي إلى Vacation الألبومات Travel ، فإن حقل القالب {folder_album} سيتوسع إلى Vacation ، Travel . إذا كانت الصورة تنتمي إلى أي ألبومات ، فسيتوسع حقل القالب {folder_album} إلى "_" (القيمة الافتراضية).
يمكن تصفية جميع حقول القالب بما في ذلك {folder_album} باستخدام عدد من المرشحات المختلفة. لتحويل جميع أسماء الدليل إلى الحالة السفلية على سبيل المثال ، استخدم المرشح lower :
osxphotos export /path/to/export --directory "{folder_album|lower}"
إذا تم تنظيم جميع الصور الخاصة بك في ألبومات مختلفة تحت مجلد اسمه Events ولكن بعضها تم تضمينه أيضًا في ألبومات أخرى من المستوى الأعلى وأردت تصدير مجلد Events فقط ، فيمكنك استخدام خيار filter لتصفية الألبومات الأخرى ذات المستوى الأعلى عن طريق اختيار مسارات المجلد/الألبوم فقط التي تبدأ Events :
osxphotos export /path/to/export --directory "{folder_album|filter(startswith Events)}"
يمكنك معرفة المزيد عن المرشحات الأخرى باستخدام osxphotos help export .
بشكل افتراضي ، سيستخدم OsxPhotos اسم الملف الأصلي للصورة عند التصدير. وهذا هو ، اسم الملف الذي كانت عليه الصورة عندما تم التقاطها أو استيرادها إلى صور. غالبًا ما يكون هذا مثل IMG_1234.JPG أو DSC05678.dng . يتيح لك OSXPHOTOS تحديد قالب اسم ملف مخصص باستخدام خيار --filename بنفس الطريقة التي يتيح لك بها --directory تحديد اسم دليل مخصص. على سبيل المثال ، تتيح لك الصور تحديد عنوان أو تعليق على صورة ويمكنك استخدام هذا بدلاً من اسم الملف الأصلي:
osxphotos export /path/to/export --filename "{title}"
سيقوم الأمر أعلاه بتصدير الصور باستخدام العنوان. لاحظ أنك لست بحاجة إلى تحديد الامتداد كجزء من قالب --filename حيث سيقوم OSXPhotos بإضافة ملحق الملف الصحيح تلقائيًا. قد لا تحتوي بعض الصور على عنوان لذلك في هذه الحالة ، يمكنك استخدام ميزة القيمة الافتراضية لتحديد اسم مختلف لهذه الصور. على سبيل المثال ، لاستخدام العنوان كاسم الملف ، ولكن إذا لم يتم تحديد عنوان ، استخدم اسم الملف الأصلي بدلاً من ذلك:
osxphotos export /path/to/export --filename "{title,{original_name}}"
│ ││ │
│ ││ │
Use photo's title as the filename <──────┘ ││ │
││ │
Value after comma will be used <───────┘│ │
if title is blank │ │
│ │
The default value can be <────┘ │
another template field │
│
Use photo's original name if no title <──────┘
يسمح نظام قالب OSXPHOTOS أيضًا بمنطق مشروط محدود من النوع "إذا كان الشرط صحيحًا ، فقم بعمل شيء واحد ، وإلا ، افعل شيئًا مختلفًا". على سبيل المثال ، يمكنك استخدام خيار --filename لتسمية الملفات التي يتم تمييزها على أنها "المفضلة" في الصور بشكل مختلف عن الملفات الأخرى. على سبيل المثال ، لإضافة "#" إلى اسم كل صورة مفضلة:
osxphotos export /path/to/export --filename "{original_name}{favorite?#,}"
│ │ │││
│ │ │││
Use photo's original name as filename <──┘ │ │││
│ │││
'favorite' is True if photo is a Favorite, <───────┘ │││
otherwise, False │││
│││
'?' specifies a conditional <─────────────┘││
││
Value immediately following ? will be used if <──────┘│
preceding template field is True or non-blank │
│
Value immediately following comma will be used if <──────┘
template field is False or blank (null); in this case
no value is specified so a blank string "" will be used
كما هو الحال مع --directory ، قد يؤدي استخدام حقل قالب متعدد القيمة مثل {keyword} إلى أكثر من نسخة واحدة من الصورة التي يتم تصديرها. على سبيل المثال ، إذا كان IMG_1234.JPG يحتوي على كلمات رئيسية Travel ، Vacation وتدير الأمر التالي:
osxphotos export /path/to/export --filename "{keyword}-{original_name}"
ستكون الملفات المصدرة:
/path/to/export/Travel-IMG_1234.JPG
/path/to/export/Vacation-IMG_1234.JPG
إذا تم تحرير صورة في الصور (على سبيل المثال ، تم تعديلها ، وما إلى ذلك) ، فستكون هناك صورة أصلية وصورة تم تحريرها في مكتبة الصور. بشكل افتراضي ، ستقوم OSXPHOTOS بتصدير الصورة الأصلية والمعدلة. للتمييز بينهما ، سيقوم Osxphotos بإلحاق "_EDITED" على الصورة المعدلة. على سبيل IMG_1234_edited.jpeg ، إذا تم تسمية الصورة الأصلية IMG_1234.JPG ، فسيقوم OSXPHOTOS بتصدير النسخة الأصلية باسم IMG_1234.JPG ملاحظة: تغير الصور تمديد الصور المعدلة إلى ".jpeg" حتى لو تم تسمية النسخة الأصلية ".jpg". يمكنك تغيير اللاحقة الملحقة إلى الصور التي تم تحريرها باستخدام خيار --edited-suffix :
osxphotos export /path/to/export --edited-suffix "_EDIT"
في هذا المثال ، سيتم تسمية الصورة المعدلة IMG_1234_EDIT.jpeg . مثل العديد من الخيارات في OSXPHOTOS ، يمكن لخيار --edited-suffix تقييم سلسلة قالب OSXPHOTOS حتى تتمكن من إلحاق تاريخ التعديل (تاريخ تحرير الصورة) لجميع الصور المعدلة باستخدام هذا الأمر:
osxphotos export /path/to/export --edited-suffix "_{modified.year}-{modified.mm}-{modified.dd}"
في هذا المثال ، إذا تم تحرير الصورة في 21 أبريل 2021 ، فإن اسم الملف المصدر سيكون: IMG_1234_2021-04-21.jpeg .
يمكنك إخبار OSXPHOTOS بعدم تصدير الصور المحررة (أي فقط تصدير الصور الأصلية غير المحررة) باستخدام --skip-edited :
osxphotos export /path/to/export --skip-edited
يمكنك أيضًا إخبار OSXPHOTOS بتصدير إما الصورة الأصلية (إذا لم يتم تحرير الصورة) أو الصورة المعدلة (إذا تم تحريرها) ، ولكن ليس كلاهما ، باستخدام الخيار --skip-original-if-edited :
osxphotos export /path/to/export --skip-original-if-edited
كما ذكر أعلاه ، تقوم الصور بإعادة تسمية صور JPEG التي تم تحريرها باستخدام امتداد ".jpeg". تستخدم بعض التطبيقات ".jpg" والبعض الآخر يستخدم ".jpg" أو ".jpeg". يمكنك استخدام خيار- --jpeg-ext لإعادة تسمية OSXPhotos على جميع ملفات JPEG بنفس الامتداد. القيم الصالحة هي JPEG ، JPG ، JPEG ، JPG ؛ على سبيل المثال- --jpeg-ext jpg لاستخدام '.jpg' لجميع jpegs.
osxphotos export /path/to/export --jpeg-ext jpg
تعمل جميع الأوامر المذكورة أعلاه على مكتبة الصور الافتراضية. يستخدم معظم المستخدمين فقط مكتبة صور واحدة تُعرف أيضًا باسم مكتبة صور النظام. من الممكن استخدام الصور مع أكثر من مكتبة واحدة. على سبيل المثال ، إذا قمت بإمساك مفتاح "الخيار" أثناء فتح الصور ، فيمكنك تحديد مكتبة صور بديلة. إذا لم تحدد المكتبة التي يجب استخدامها ، فسيحاول OsxPhotos العثور على آخر مكتبة مفتوحة. في بعض الأحيان لا يمكن تحديد ذلك وفي هذه الحالة ، سيستخدم مكتبة صور النظام. إذا كنت تستخدم أكثر من مكتبة صور واحدة وترغب في تحديد المكتبة بشكل صريح ، فيمكنك القيام بذلك باستخدام خيار --library .
osxphotos export /path/to/export --library ~/Pictures/MyAlternateLibrary.photoslibrary
يعمل OsxPhotos عن طريق نسخ الصور من مجلد مكتبة الصور لتصديرها. قد ترى أن OSXPHOTOS تقرير أن صورة واحدة أو أكثر مفقودة وبالتالي لا يمكن تصديرها. أحد الأسباب المحتملة لذلك هو أنك تستخدم ICLOUD لمزامنة مكتبة الصور الخاصة بك ، ولم تقم الصور إما بمزامنة مكتبة السحابة إلى جهاز MAC المحلي أو لديك صور تم تكوينها "لتحسين تخزين Mac" في تفضيلات الصور. سبب آخر هو أنه حتى إذا كان لديك صور تم تكوينها لتنزيل Originals على جهاز Mac ، فإن الصور لا تقوم دائمًا بتنزيل الصور من الألبومات المشتركة أو لقطات الشاشة الأصلية إلى Mac.
إذا واجهت صورًا مفقودة ، فيمكنك إخبار OSXPHOTOS بتنزيل الصور المفقودة من ICLOUD باستخدام خيار --download-missing . --download-missing Applescript للتواصل مع الصور وأخبرها بتنزيل الصور المفقودة. واجهة Applescript Photos 'هي عربات التي تجرها الدواب إلى حد ما وقد تجد أن الصور تعطل. في هذه الحالة ، سيحاول Osxphotos إعادة تشغيل الصور لاستئناف عملية التنزيل. هناك أيضًا خيار تجريبي --use-photokit سيتواصل مع الصور باستخدام واجهة "photokit" مختلفة. يجب استخدام هذا الخيار مع --download-missing :
osxphotos export /path/to/export --download-missing
osxphotos export /path/to/export --download-missing --use-photokit
إذا كنت تقوم بتصدير إلى جهاز تخزين خارجي مرفق (NAS) ، فقد تواجه أخطاء إذا كان اتصال الشبكة غير موثوق به. في هذه الحالة ، يمكنك استخدام خيار --retry بحيث يقوم OSXPhotos بإعادة إعادة تصدير OSXPHOTOS تلقائيًا. استخدم --retry مع رقم يحدد عدد المرات لإعادة محاولة التصدير:
osxphotos export /path/to/export --retry 3
في هذا المثال ، سيحاول Osxphotos تصدير صورة تصل إلى 3 مرات إذا واجهت خطأً.
بالإضافة إلى --retry ، قد --exportdb و --ramdb قد يحسن الأداء عند التصدير إلى قرص خارجي أو NAS. عندما يقوم OSXPHOTOS بتصدير الصور ، فإنه ينشئ ملف قاعدة بيانات تصدير يسمى .osxphotos_export.db في مجلد التصدير الذي يستخدمه OSXPHOTOS لتتبع الصور التي تم تصديرها. يتيح لك ذلك إعادة تشغيل وتصدير واستخدام --update تصدير موجود. إذا كان الاتصال إلى موقع التصدير بطيئًا أو قشاريًا ، فقد يؤدي وجود قاعدة بيانات التصدير على قرص التصدير إلى تقليل الأداء. في هذه الحالة ، يمكنك استخدام --exportdb DBPATH لتوجيه OSXPHOTOS لتخزين قاعدة بيانات التصدير في DBPATH. إذا كنت أستخدم هذا الخيار ، أوصي بوضع قاعدة بيانات التصدير على قرص نظام Mac الخاص بك (على سبيل المثال ، في الدليل الرئيسي). إذا كنت تنوي استخدام --update التصدير في المستقبل ، فيجب أن تتذكر مكان وجود قاعدة بيانات التصدير واستخدام خيار --exportdb في كل مرة تقوم فيها بتحديث التصدير.
بديل آخر لاستخدام --exportdb هو الاستخدام --ramdb . يرشد هذا الخيار OSXPHOTOS باستخدام قاعدة بيانات RAM بدلاً من ملف على القرص. قاعدة بيانات RAM أسرع بكثير من الملف الموجود على القرص ولا تتطلب OSXPHOTOS الوصول إلى محرك الشبكة للاستعلام أو الكتابة إلى قاعدة البيانات. عندما يكمل OSXPHOTOS التصدير ، فسوف يكتب قاعدة بيانات RAM إلى موقع التصدير. يمكن أن يوفر هذا دفعة كبيرة للأداء ، لكنك ستفقد معلومات الدولة إذا تعطل OsxPhotos أو تم مقاطعة أثناء التصدير.
تتبع الصور كمية هائلة من البيانات الوصفية المرتبطة بالصور في المكتبة مثل الكلمات الرئيسية والوجوه والأشخاص وبيانات تحديد الموقع الجغرافي العكسي وعلامات تصنيف الصور. قدرة التصدير الأصلية لا تحافظ على معظم هذه البيانات الوصفية. ومع ذلك ، يمكن لـ OSXPHOTOS الوصول إلى جميع البيانات الأولية المرتبطة بالصور والحفاظ عليها تقريبًا. باستخدام تطبيق exiftool المجاني ، يمكن لـ OSXPHOTOS كتابة البيانات الوصفية لتصدير الصور. اتبع الإرشادات الموجودة على موقع Exiftool لتثبيت Exiftool ثم يمكنك استخدام خيار --exiftool لكتابة البيانات الوصفية لتصدير الصور:
osxphotos export /path/to/export --exiftool
سيؤدي ذلك إلى كتابة البيانات الوصفية الأساسية مثل الكلمات الرئيسية والأشخاص وموقع GPS إلى الملفات المصدرة. يتضمن Osxphotos العديد من الخيارات الإضافية التي يمكن استخدامها بالاقتران مع --exiftool لتعديل البيانات الوصفية التي كتبها exiftool . على سبيل المثال ، يمكنك استخدام خيار- --keyword-template لتحديد الكلمات الرئيسية المخصصة (مرة أخرى ، عبر نظام قالب OSXPHOTOS). على سبيل المثال ، لاستخدام المجلد والألبوم صورة موجودة لإنشاء كلمات رئيسية هرمية بالتنسيق الذي تستخدمه Lightroom Classic:
osxphotos export /path/to/export --exiftool --keyword-template "{folder_album(>)}"
│ │
│ │
folder_album results in the folder(s) <──┘ │
and album a photo is contained in │
│
The value in () is used as the path separator <───────┘
for joining the folders and albums. For example,
if photo is in Folder1/Folder2/Album, (>) produces
"Folder1>Folder2>Album" which some programs, such as
Lightroom Classic, treat as hierarchical keywords
سيقوم الأمر أعلاه بكتابة جميع البيانات --exiftool العادية التي تكتب عادةً إلى الملف عند التصدير ولكنها ستضيف أيضًا كلمة رئيسية إضافية في الألبوم المصدر في النموذج "Folder1> Folder2>". إذا لم تقم بتضمين (>) في سلسلة القالب (على سبيل المثال {folder_album} ) ، فسيتم عرض Folder_Album في النموذج "Folder1/Folder2/Album".
تتمثل الميزة القوية في الصور في أنه يستخدم خوارزميات تعلم الآلة لتصنيف الصور أو تصنيفها تلقائيًا. يتم استخدام هذه الملصقات عند البحث عن الصور في الصور ولكنها غير متوفرة للمستخدم. يمكن لـ OSXPHOTOS قراءة جميع الملصقات المرتبطة بالصورة ويجعل تلك المتاحة من خلال نظام القالب عبر {label} . فكر في هذه الكلمات الرئيسية التلقائية على عكس الكلمات الرئيسية التي تقوم بتعيينها يدويًا في الصور. تتمثل إحدى حالات الاستخدام الشائعة في استخدام الملصقات التلقائية لإنشاء كلمات رئيسية جديدة عند تصدير الصور بحيث يتم تضمين هذه الملصقات في بيانات تعريف الصورة:
osxphotos export /path/to/export --exiftool --keyword-template "{label}"
إذا كانت بعض الصور الخاصة بك تحتوي على كلمة رئيسية لا تريد إضافتها إلى الملف الذي تم تصديره مع --exiftool ، فيمكنك استخدام نظام القالب لإزالة الكلمة الرئيسية من الملف الذي تم تصديره. على سبيل المثال ، إذا كنت تريد إزالة الكلمة الرئيسية "MyKeyword" من جميع صورك:
osxphotos export /path/to/export --exiftool --keyword-template "{keyword|remove(MyKeyword)}" --replace-keywords
في هذا المثال ، |remove(MyKeyword) هو مرشح يزيل MyKeyword من قائمة الكلمات الرئيسية لكل صورة تتم معالجتها. يقوم خيار- --replace-keywords بتوجيه OSXPHOTOS لاستبدال الكلمات الرئيسية في الملف المصدر بالكلمات الرئيسية المصفاة من- --keyword-template .
ملاحظة : عند تقييم القوالب لـ --directory و --filename ، يقوم OsxPhotos بإدراج القيمة الافتراضية التلقائية "_" لأي حقل قالب فارغ (فارغ أو فارغ). هذا هو التأكد من أنه لا يوجد دليل فارغ أو اسم ملف. بالنسبة لقوالب البيانات الوصفية مثل- --keyword-template ، لا يوفر OsxPhotos قيمة افتراضية تلقائية وبالتالي إذا كان حقل القالب لاغيرًا ، فلن يتم إنشاء أي كلمة رئيسية. بالطبع ، يمكنك توفير قيمة افتراضية إذا رغبت في ذلك وسيستخدم OSXPhotos هذا. على سبيل المثال ، لإضافة "Nolabel" ككلمة رئيسية لأي صورة لا تحتوي على ملصقات:
osxphotos export /path/to/export --exiftool --keyword-template "{label,nolabel}"
هناك طريقة أخرى لتصدير البيانات الوصفية حول صورك وهي من خلال استخدام ملفات Sidecar. هذه هي الملفات التي لها نفس اسم صورتك (ولكن مع امتداد مختلف) وتحمل البيانات الوصفية. يمكن للعديد من تطبيقات إدارة الأصول الرقمية (على سبيل المثال ، التصوير الضوئي ، Lightroom ، Digikam ، إلخ) قراءة أو كتابة ملفات Sidecar. يمكن لـ OSXPHOTOS تصدير البيانات الوصفية في تنسيقات JSON و XMP المتوافقة مع exiftool باستخدام خيار --sidecar . على سبيل المثال ، لإخراج البيانات الوصفية إلى Sidecars XMP:
osxphotos export /path/to/export --sidecar XMP
على عكس --exiftool ، لا تحتاج إلى تثبيت Exiftool لاستخدام ميزة --sidecar . العديد من خيارات التكوين نفسها التي تنطبق على- --exiftool لتعديل البيانات الوصفية ، على سبيل المثال ،-يمكن أيضًا استخدام- --keyword-template --sidecar .
تتم تسمية ملفات Sidecar "photoname.ext.sidecar_ext". على سبيل المثال ، إذا تم تسمية الصورة IMG_1234.JPG وتنسيق SIDECAR هو XMP ، فسيتم تسمية SIDECAR IMG_1234.JPG.XMP . تتوقع بعض التطبيقات تسمية Sidecar في هذه الحالة IMG_1234.XMP . يمكنك استخدام خيار- --sidecar-drop-ext لإجبار OSXPHOTOS على تسمية ملفات SIDECAR بهذه الطريقة:
osxphotos export /path/to/export --sidecar XMP --sidecar-drop-ext
إذا كنت ترغب في استخدام OSXPHOTOS لإجراء نسخ احتياطية دورية لمكتبة الصور الخاصة بك بدلاً من تصدير لمرة واحدة ، فاستخدم خيار --update . عند تشغيل osxphotos export ، فإنه ينشئ ملف قاعدة بيانات يسمى .osxphotos_export.db في مجلد التصدير. ( لاحظ لأن اسم الملف يبدأ بـ "." ، لن تراه في Finder يعامل "ملفات النقطة" مثل هذا مخفي. سترى الملف في المحطة.). إذا قمت بتشغيل OSXPHOTOS مع خيار --update ، فسوف يبحث عن ملف قاعدة البيانات هذا ، وإذا وجد ، استخدمه لاسترداد معلومات الحالة من آخر مرة تم تشغيلها لتصدير الملفات الجديدة أو المتغيرة فقط. على سبيل المثال:
osxphotos export /path/to/export --update
سوف تقرأ قاعدة بيانات التصدير الموجودة في /path/to/export/.osxphotos_export.db /.osxphotos_export.db وتصدير فقط الصور التي تمت إضافتها أو تغييرها منذ آخر مرة تم فيها تشغيل OsxPhotos. يمكنك تشغيل OSXPHOTOS مع خيار --update حتى لو لم يتم تشغيله من قبل. إذا لم يتم العثور على قاعدة البيانات ، فسيقوم OSXPHOTOS بإنشائها. إذا قمت بتشغيل osxphotos export بدون --update في مجلد حيث قمت مسبقًا بتصدير الصور ، فسيتم إعادة تصدير جميع الصور. إذا كانت نيتك هي الحفاظ على نسخة احتياطية دورية لمكتبة الصور الخاصة بك مع OSXPHOTOS ، فيجب عليك دائمًا --update .
إذا كان سير العمل الخاص بك يتضمن نقل الملفات من دليل التصدير (على سبيل المثال ، تقوم بنقلها إلى تطبيق إدارة الأصول الرقمية) ولكنك تريد استخدام ميزات --update ، يمكنك استخدام --only-new مع --update لإجبار OSXPHOTOs على تصدير الصور الجديدة فقط (تمت إضافتها إلى المكتبة) منذ التحديث الأخير. في هذه الحالة ، سيتجاهل OsxPhotos الملفات التي تم تصديرها مسبقًا مفقودة الآن. بدون --only-new ، سيرى Osxphotos أن الملفات التي تم تصديرها مسبقًا مفقودة وإعادة تصديرها.
osxphotos export /path/to/export --update --only-new
إذا كان سير العمل الخاص بك يتضمن تحرير الصور التي قمت بتصديرها من الصور ، لكنك لا تزال ترغب في الحفاظ على نسخة احتياطية مع --update ، فيجب عليك استخدام خيار --ignore-signature . -يرشط --ignore-signature OSXPHOTOS لتجاهل توقيع الملف (على سبيل المثال ، الحجم والتاريخ المعدلة) عند تحديد الملفات التي يجب تحديثها باستخدام --update . إذا قمت بتحرير ملف في دليل التصدير ثم قم بتشغيل --update بدون --ignore-signature ، سيرى Osxphotos أن الملف يختلف عن البرنامج الموجود في مكتبة الصور وإعادة تصديره.
osxphotos export /path/to/export --update --ignore-signature
يمكنك استخدام الخيار --dry-run للحصول على "تشغيل جاف" OSXPHOTOS أو اختبار تصدير دون تصدير أي ملفات فعليًا. عندما يتم دمجها مع خيار --verbose ، الذي يتسبب في طباعة OSXPHOTOS تفاصيل كل ملف يتم تصديره ، يمكن أن يكون هذا أداة مفيدة لاختبار خيارات التصدير الخاصة بك قبل تشغيل تصدير كامل بالفعل. على سبيل المثال ، إذا كنت تتعلم نظام القالب وترغب في التحقق من أن قوالب --directory و- --filename هي صحيحة ، --dry-run --verbose بطباعة اسم كل ملف يتم تصديره.
osxphotos export /path/to/export --dry-run --verbose
يمكنك استخدام خيار --report عن إنشاء تقرير ، بتنسيق القيم المفصلية (CSV) الذي يسرد تفاصيل جميع الملفات التي تم تصديرها ، تخطي ، مفقودة ، وما إلى ذلك. هذا تنسيق الملف متوافق مع برامج مثل Microsoft Excel. قدم اسم التقرير بعد خيار --report :
osxphotos export /path/to/export --report export.csv
يمكنك أيضًا إنشاء تقارير بتنسيق JSON أو SQLite عن طريق تغيير تمديد اسم ملف التقرير. على سبيل المثال ، لإنشاء تقرير JSON:
osxphotos export /path/to/export --report export.json
وإنشاء تقرير sqlite:
osxphotos export /path/to/export --report export.sqlite
بشكل افتراضي ، ستقوم OsxPhotos بتصدير مكتبة الصور بأكملها. إذا كنت ترغب في تصدير صور معينة فقط ، فإن OsxPhotos يوفر مجموعة غنية من "خيارات الاستعلام" التي تتيح لك الاستعلام عن قاعدة بيانات الصور لتصفية الصور فقط التي تتطابق مع معايير الاستعلام الخاصة بك. لا يغطي البرنامج التعليمي جميع خيارات الاستعلام حيث يوجد أكثر من 50 منهم-إعادة قراءة نص المساعدة ( osxphotos help export ) لفهم خيارات الاستعلام المتاحة بشكل أفضل. بغض النظر عن أي مجموعة فرعية من الصور التي ترغب في تصديرها ، فمن المؤكد أن هناك وسيلة لـ Osxphotos لتصفية هذه. على سبيل المثال ، يمكنك تصفية الصور فقط التي تحتوي على كلمات أو صور معينة دون عنوان ، أو صور من وقت محدد من اليوم أو نطاق تاريخ محدد ، الصور الموجودة في ألبومات محددة ، إلخ.
على سبيل المثال ، لتصدير الصور فقط مع Travel بالكلمات الرئيسية:
osxphotos export /path/to/export --keyword "Travel"
مثل العديد من الخيارات في OSXPHOTOS ، يمكن تكرار --keyword (ومعظم خيارات الاستعلام الأخرى) للبحث عن أكثر من مصطلح واحد. على سبيل المثال ، للعثور على صور مع Travel الكلمات الرئيسية أو Vacation الكلمات الرئيسية:
osxphotos export /path/to/export --keyword "Travel" --keyword "Vacation"
لتصدير الصور فقط الواردة في ألبوم "العطلة الصيفية":
osxphotos export /path/to/export --album "Summer Vacation"
في الصور ، من الممكن أن يكون لديك ألبومات متعددة تحمل نفس الاسم. في هذه الحالة ، ستقوم Osxphotos بتصدير الصور من جميع الألبومات التي تتطابق مع القيمة التي تم تمريرها إلى --album . إذا كنت ترغب في تصدير واحد فقط من الألبومات وهذا الألبوم في مجلد ، فإن خيار --regex (قصير لـ "التعبير العادي") ، والذي يقوم بمطابقة الأنماط ، يمكن استخدامه مع قالب {folder_album} لمطابقة الألبوم المحدد. على سبيل المثال ، إذا كان لديك ألبوم "عطلة صيفية" داخل المجلد "2018" وأيضًا مع نفس الاسم داخل المجلد "2019" ، فيمكنك تصدير فقط الألبوم "2018/Summer Vacation" باستخدام هذا الأمر:
osxphotos export /path/to/export --regex "2018/Summer Vacation" "{folder_album}"
يتطابق هذا الأمر مع نمط "2018/Summer Faciture" مع مسار المجلد/الألبوم الكامل لكل صورة.
هناك أيضًا عدد من خيارات الاستعلام لتصدير أنواع معينة فقط من الصور. على سبيل المثال ، لتصدير الصور التي تم التقاطها فقط باستخدام iPhone "Mode Portrait Mode":
osxphotos export /path/to/export --portrait
يمكنك أيضًا تصدير الصور في نطاق تاريخ معين:
osxphotos export /path/to/export --from-date "2020-01-01" --to-date "2020-02-28"
أو الصور التي تمت إضافتها إلى المكتبة في الأسبوع الماضي:
osxphotos export /path/to/export --added-in-last "1 week"
يمكن للصور تخزين الصور في العديد من التنسيقات المختلفة. يمكن لـ OSXPHOTOS تحويل الصور غير JPEG (على سبيل المثال ، الصور الخام) إلى JPEG على التصدير باستخدام خيار-- --convert-to-jpeg . يمكنك تحديد جودة JPEG (0: أسوأ ، 1.0: أفضل) باستخدام --jpeg-quality . على سبيل المثال:
osxphotos export /path/to/export --convert-to-jpeg --jpeg-quality 0.9
بالإضافة إلى استخدام exiftool لكتابة البيانات الوصفية مباشرة إلى بيانات تعريف الصورة ، يمكن لـ OSXPHOTOS كتابة بيانات بيانات معينة متاحة للمكتشف والضوء ولكن لا تعدل ملف الصورة الفعلي. يتم ذلك من خلال شيء يسمى السمات الموسعة التي يتم تخزينها في نظام الملفات بملف ولكن لا تعدل الملف نفسه بالفعل. علامات الباحث وتعليقات الباحث هي أمثلة شائعة على هذه.
يمكن لـ OsxPhotos ، على سبيل المثال ، كتابة أي كلمات رئيسية في الصورة إلى علامات Finder بحيث يمكنك البحث عن الصور في Spotlight أو Finder باستخدام tag:tagname Syntax:
osxphotos export /path/to/export --finder-tag-keywords
--finder-tag-keywords تعمل أيضًا مع- --keyword-template كما هو موضح أعلاه في القسم الخاص بـ exiftool :
osxphotos export /path/to/export --finder-tag-keywords --keyword-template "{label}"
يتيح لك خيار- --xattr-template تعيين مجموعة متنوعة من السمات الموسعة الأخرى. يتم استخدامه في قالب --xattr-template ATTRIBUTE TEMPLATE حيث تكون السمة واحدة من "المؤلفين" ، "التعليق" ، "حقوق الطبع والنشر" ، "الوصف" ، "findercomment" ، "العنوان الرئيسي" ، "الكلمات الرئيسية".
على سبيل المثال ، لتعيين تعليق Finder على عنوان الصورة ووصفها:
osxphotos export /path/to/export --xattr-template findercomment "{title}{newline}{descr}"
In the template string above, {newline} instructs osxphotos to insert a new line character ("n") between the title and description. In this example, if {title} or {descr} is empty, you'll get "titlen" or "ndescription" which may not be desired so you can use more advanced features of the template system to handle these cases:
osxphotos export /path/to/export --xattr-template findercomment "{title,}{title?{descr?{newline},},}{descr,}"
Explanation of the template string:
{title,}{title?{descr?{newline},},}{descr,}
│ │ │ │ │ │ │
│ │ │ │ │ │ │
└──> insert title (or nothing if no title)
│ │ │ │ │ │
└───> is there a title?
│ │ │ │ │
└───> if so, is there a description?
│ │ │ │
└───> if so, insert new line
│ │ │
└───> if descr is blank, insert nothing
│ │
└───> if title is blank, insert nothing
│
└───> finally, insert description
(or nothing if no description)
In this example, title? demonstrates use of the boolean (True/False) feature of the template system. title? is read as "Is the title True (or not blank/empty)? If so, then the value immediately following the ? is used in place of title . If title is blank, then the value immediately following the comma is used instead. The format for boolean fields is field?value if true,value if false . Either value if true or value if false may be blank, in which case a blank string ("") is used for the value and both may also be an entirely new template string as seen in the above example. Using this format, template strings may be nested inside each other to form complex if-then-else statements.
The above example, while complex to read, shows how flexible the osxphotos template system is. If you invest a little time learning how to use the template system you can easily handle almost any use case you have.
See Extended Attributes section in the help for osxphotos export for additional information about this feature.
If you repeatedly run a complex osxphotos export command (for example, to regularly back-up your Photos library), you can save all the options to a configuration file for future use ( --save-config FILE ) and then load them ( --load-config FILE ) instead of repeating each option on the command line.
To save the configuration:
osxphotos export /path/to/export <all your options here> --update --save-config osxphotos.toml
Then the next to you run osxphotos, you can simply do this:
osxphotos export /path/to/export --load-config osxphotos.toml
The configuration file is a plain text file in TOML format so the .toml extension is standard but you can name the file anything you like.
You can use the --post-command option to run one or more commands against exported files. The --post-command option takes two arguments: CATEGORY and COMMAND. CATEGORY is a string that describes which category of file to run the command against. The available categories are described in the help text available via: osxphotos help export . For example, the exported category includes all exported photos and the skipped category includes all photos that were skipped when running export with --update . COMMAND is an osxphotos template string which will be rendered then passed to the shell for execution.
For example, the following command generates a log of all exported files and their associated keywords:
osxphotos export /path/to/export --post-command exported "echo {shell_quote,{filepath}{comma}{,+keyword,}} >> {shell_quote,{export_dir}/exported.txt}"
The special template field {shell_quote} ensures a string is properly quoted for execution in the shell. For example, it's possible that a file path or keyword in this example has a space in the value and if not properly quoted, this would cause an error in the execution of the command. When running commands, the template {filepath} is set to the full path of the exported file and {export_dir} is set to the full path of the base export directory.
Explanation of the template string:
{shell_quote,{filepath}{comma}{,+keyword,}}
│ │ │ │ │
│ │ │ | │
└──> quote everything after comma for proper execution in the shell
│ │ │ │
└───> filepath of the exported file
│ │ │
└───> insert a comma
│ │
└───> join the list of keywords together with a ","
│
└───> if no keywords, insert nothing (empty string: "")
Another example: if you had exiftool installed and wanted to wipe all metadata from all exported files, you could use the following:
osxphotos export /path/to/export --post-command exported "/usr/local/bin/exiftool -all= {filepath|shell_quote}"
This command uses the |shell_quote template filter instead of the {shell_quote} template because the only thing that needs to be quoted is the path to the exported file. Template filters filter the value of the rendered template field. A number of other filters are available and are described in the help text.
Here's a comprehensive use case from an actual osxphotos user that integrates many of the concepts discussed in this tutorial (thank-you Philippe for contributing this!):
I usually import my iPhone’s photo roll on a more or less regular basis, and it
includes photos and videos. As a result, the size ot my Photos library may rise
very quickly. Nevertheless, I will tag and geolocate everything as Photos has a
quite good keyword management system.
After a while, I want to take most of the videos out of the library and move them
to a separate "videos" folder on a different folder / volume. As I might want to
use them in Final Cut Pro, and since Final Cut is able to import Finder tags into
its internal library tagging system, I will use osxphotos to do just this.
Picking the videos can be left to Photos, using a smart folder for instance. Then
just add a keyword to all videos to be processed. Here I chose "Quik" as I wanted
to spot all videos created on my iPhone using the Quik application (now part of
GoPro).
I want to retrieve my keywords only and make sure they populate the Finder tags, as
well as export all the persons identified in the videos by Photos. I also want to
merge any keywords or persons already in the video metadata with the exported
metadata.
Keeping Photo’s edited titles and descriptions and putting both in the Finder
comments field in a readable manner is also enabled.
And I want to keep the file’s creation date (using `--touch-file`).
Finally, use `--strip` to remove any leading or trailing whitespace from processed
template fields.
osxphotos export ~/Desktop/folder for exported videos/ --keyword Quik --only-movies --library /path to my.photoslibrary --touch-file --finder-tag-keywords --person-keyword --xattr-template findercomment "{title}{title?{descr?{newline},},}{descr}" --exiftool-merge-keywords --exiftool-merge-persons --exiftool --strip
Some osxphotos commands such as export use color themes to colorize the output to make it more legible. The theme may be specified with the --theme option. For example: osxphotos export /path/to/export --verbose --theme dark uses a theme suited for dark terminals. If you don't specify the color theme, osxphotos will select a default theme based on the current terminal settings. You can also specify your own default theme. See osxphotos help theme for more information on themes and for commands to help manage themes. Themes are defined in .theme files in the ~/.osxphotos/themes directory and use style specifications compatible with the rich library.
osxphotos is very flexible. If you merely want to backup your Photos library, then spending a few minutes to understand the --directory option is likely all you need and you can be up and running in minutes. However, if you have a more complex workflow, osxphotos likely provides options to implement your workflow. This tutorial does not attempt to cover every option offered by osxphotos but hopefully it provides a good understanding of what kinds of things are possible and where to explore if you want to learn more.
osxphotos help export
Usage: osxphotos export [OPTIONS] DEST
Export photos from the Photos database. Export path DEST is required.
Optionally, query the Photos database using 1 or more search options; if more
than one different option is provided, they are treated as "AND" (e.g. search
for photos matching all options). If the same query option is provided
multiple times, they are treated as "OR" (e.g. search for photos matching any
of the options). If no query options are provided, all photos will be
exported.
For example, adding the query options:
--person "John Doe" --person "Jane Doe" --keyword "vacation"
will export all photos with either person of ("John Doe" OR "Jane Doe") AND
keyword of "vacation"
By default, all versions of all photos will be exported including edited
versions, live photo movies, burst photos, and associated raw images. See
--skip-edited, --skip-live, --skip-bursts, and --skip-raw options to modify
this behavior.
Options:
--library, --db PHOTOS_LIBRARY_PATH
Specify path to Photos library. If not
provided, will attempt to find the library to
use in the following order: 1. last opened
library, 2. system library, 3.
~/Pictures/Photos Library.photoslibrary
-V, --verbose Print verbose output; may be specified
multiple times for more verbose output.
--timestamp Add time stamp to verbose output
--no-progress Do not display progress bar during export.
--keyword KEYWORD Search for photos with keyword KEYWORD. If
more than one keyword, treated as "OR", e.g.
find photos matching any keyword
--no-keyword Search for photos with no keyword.
--person PERSON Search for photos with person PERSON. If more
than one person, treated as "OR", e.g. find
photos matching any person
--album ALBUM Search for photos in album ALBUM. If more than
one album, treated as "OR", e.g. find photos
matching any album
--folder FOLDER Search for photos in an album in folder
FOLDER. If more than one folder, treated as
"OR", e.g. find photos in any FOLDER. Only
searches top level folders (e.g. does not look
at subfolders)
--name FILENAME Search for photos with filename matching
FILENAME. If more than one --name options is
specified, they are treated as "OR", e.g. find
photos matching any FILENAME.
--uuid UUID Search for photos with UUID(s). May be
repeated to include multiple UUIDs.
--uuid-from-file FILE Search for photos with UUID(s) loaded from
FILE. Format is a single UUID per line. Lines
preceded with # are ignored. If FILE is '-',
read UUIDs from stdin.
--title TITLE Search for TITLE in title of photo.
--no-title Search for photos with no title.
--description DESC Search for DESC in description of photo.
--no-description Search for photos with no description.
--place PLACE Search for PLACE in photo's reverse
geolocation info
--no-place Search for photos with no associated place
name info (no reverse geolocation info)
--location Search for photos with associated location
info (e.g. GPS coordinates)
--no-location Search for photos with no associated location
info (e.g. no GPS coordinates)
--label LABEL Search for photos with image classification
label LABEL (Photos 5+ only). If more than one
label, treated as "OR", e.g. find photos
matching any label
--uti UTI Search for photos whose uniform type
identifier (UTI) matches UTI
-i, --ignore-case Case insensitive search for title,
description, place, keyword, person, or album.
--edited Search for photos that have been edited.
--not-edited Search for photos that have not been edited.
--external-edit Search for photos edited in external editor.
--favorite Search for photos marked favorite.
--not-favorite Search for photos not marked favorite.
--hidden Search for photos marked hidden.
--not-hidden Search for photos not marked hidden.
--shared Search for photos in shared iCloud album
(Photos 5+ only).
--not-shared Search for photos not in shared iCloud album
(Photos 5+ only).
--burst Search for photos that were taken in a burst.
--not-burst Search for photos that are not part of a
burst.
--live Search for Apple live photos
--not-live Search for photos that are not Apple live
photos.
--portrait Search for Apple portrait mode photos.
--not-portrait Search for photos that are not Apple portrait
mode photos.
--screenshot Search for screenshot photos.
--not-screenshot Search for photos that are not screenshot
photos.
--screen-recording Search for screen-recording videos.
--not-screen-recording Search for photos that are not screen
recording videos.
--slow-mo Search for slow motion videos.
--not-slow-mo Search for photos that are not slow motion
videos.
--time-lapse Search for time lapse videos.
--not-time-lapse Search for photos that are not time lapse
videos.
--hdr Search for high dynamic range (HDR) photos.
--not-hdr Search for photos that are not HDR photos.
--selfie Search for selfies (photos taken with front-
facing cameras).
--not-selfie Search for photos that are not selfies.
--panorama Search for panorama photos.
--not-panorama Search for photos that are not panoramas.
--has-raw Search for photos with both a jpeg and raw
version
--only-movies Search only for movies (default searches both
images and movies).
--only-photos Search only for photos/images (default
searches both images and movies).
--from-date DATE Search for items created on or after DATE,
e.g. 2000-01-12T12:00:00,
2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO
8601 with/without timezone).
--to-date DATE Search for items created before DATE, e.g.
2000-01-12T12:00:00,
2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO
8601 with/without timezone).
--from-time TIME Search for items created on or after TIME of
day, e.g. 12:00, or 12:00:00.
--to-time TIME Search for items created before TIME of day,
e.g. 12:00 or 12:00:00.
--year YEAR Search for items from a specific year, e.g.
--year 2022 to find all photos from the year
2022. May be repeated to search multiple
years.
--added-before DATE Search for items added to the library before a
specific date/time, e.g. --added-before e.g.
2000-01-12T12:00:00,
2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO
8601 with/without timezone).
--added-after DATE Search for items added to the library on or
after a specific date/time, e.g. --added-after
e.g. 2000-01-12T12:00:00,
2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO
8601 with/without timezone).
--added-in-last TIME_DELTA Search for items added to the library in the
last TIME_DELTA, where TIME_DELTA is a string
like '12 hrs', '1 day', '1d', '1 week',
'2weeks', '1 month', '1 year'. for example,
`--added-in-last 7d` and `--added-in-last '1
week'` are equivalent. months are assumed to
be 30 days and years are assumed to be 365
days. Common English abbreviations are
accepted, e.g. d, day, days or m, min,
minutes.
--has-comment Search for photos that have comments.
--no-comment Search for photos with no comments.
--has-likes Search for photos that have likes.
--no-likes Search for photos with no likes.
--is-reference Search for photos that were imported as
referenced files (not copied into Photos
library).
--not-reference Search for photos that are not references,
that is, they were copied into the Photos
library and are managed by Photos.
--in-album Search for photos that are in one or more
albums.
--not-in-album Search for photos that are not in any albums.
--duplicate Search for photos with possible duplicates.
osxphotos will compare signatures of photos,
evaluating date created, size, height, width,
and edited status to find *possible*
duplicates. This does not compare images byte-
for-byte nor compare hashes but should find
photos imported multiple times or duplicated
within Photos.
--min-size SIZE Search for photos with size >= SIZE bytes. The
size evaluated is the photo's original size
(when imported to Photos). Size may be
specified as integer bytes or using SI or NIST
units. For example, the following are all
valid and equivalent sizes: '1048576'
'1.048576MB', '1 MiB'.
--max-size SIZE Search for photos with size <= SIZE bytes. The
size evaluated is the photo's original size
(when imported to Photos). Size may be
specified as integer bytes or using SI or NIST
units. For example, the following are all
valid and equivalent sizes: '1048576'
'1.048576MB', '1 MiB'.
--missing Search for photos missing from disk.
--not-missing Search for photos present on disk (e.g. not
missing).
--cloudasset Search for photos that are part of an iCloud
library
--not-cloudasset Search for photos that are not part of an
iCloud library
--incloud Search for photos that are in iCloud (have
been synched)
--not-incloud Search for photos that are not in iCloud (have
not been synched)
--syndicated Search for photos that have been shared via
syndication ('Shared with You' album via
Messages, etc.)
--not-syndicated Search for photos that have not been shared
via syndication ('Shared with You' album via
Messages, etc.)
--saved-to-library Search for syndicated photos that have saved
to the library
--not-saved-to-library Search for syndicated photos that have not
saved to the library
--shared-moment Search for photos that are part of a shared
moment
--not-shared-moment Search for photos that are not part of a
shared moment
--shared-library Search for photos that are part of a shared
library
--not-shared-library Search for photos that are not part of a
shared library
--regex REGEX TEMPLATE Search for photos where TEMPLATE matches
regular expression REGEX. For example, to find
photos in an album that begins with 'Beach': '
--regex "^Beach" "{album}"'. You may specify
more than one regular expression match by
repeating '--regex' with different arguments.
--selected Filter for photos that are currently selected
in Photos.
--exif EXIF_TAG VALUE Search for photos where EXIF_TAG exists in
photo's EXIF data and contains VALUE. For
example, to find photos created by Adobe
Photoshop: `--exif Software 'Adobe Photoshop'
`or to find all photos shot on a Canon camera:
`--exif Make Canon`. EXIF_TAG can be any valid
exiftool tag, with or without group name, e.g.
`EXIF:Make` or `Make`. To use --exif, exiftool
must be installed and in the path.
--query-eval CRITERIA Evaluate CRITERIA to filter photos. CRITERIA
will be evaluated in context of the following
python list comprehension: `photos = [photo
for photo in photos if CRITERIA]` where photo
represents a PhotoInfo object. For example:
`--query-eval photo.favorite` returns all
photos that have been favorited and is
equivalent to --favorite. You may specify more
than one CRITERIA by using --query-eval
multiple times. CRITERIA must be a valid
python expression. See
https://rhettbull.github.io/osxphotos/ for
additional documentation on the PhotoInfo
class.
--query-function filename.py::function
Run function to filter photos. Use this in
format: --query-function filename.py::function
where filename.py is a python file you've
created and function is the name of the
function in the python file you want to call.
Your function will be passed a list of
PhotoInfo objects and is expected to return a
filtered list of PhotoInfo objects. You may
use more than one function by repeating the
--query-function option with a different
value. Your query function will be called
after all other query options have been
evaluated. You may also specify a URL to a
python file in the format: --query-function
https://path/to/module.py::function See https:
//github.com/RhetTbull/osxphotos/blob/master/e
xamples/query_function.py for example of a
query function.
--deleted-only Include only photos from the 'Recently
Deleted' folder.
--deleted Include photos from the 'Recently Deleted'
folder.
--update Only export new or updated files. See also
--force-update and notes below on export and
--update.
--force-update Only export new or updated files. Unlike
--update, --force-update will re-export photos
if their metadata has changed even if this
would not otherwise trigger an export. See
also --update and notes below on export and
--update.
--update-errors Update files that were previously exported but
produced errors during export. For example, if
a file produced an error with --exiftool due
to bad metadata, this option will re-export
the file and attempt to write the metadata
again when used with --exiftool and --update.
Without --update-errors, photos that were
successfully exported but generated an error
or warning during export will not be re-
attempted if metadata has not changed. Must be
used with --update.
--ignore-signature When used with '--update', ignores file
signature when updating files. This is useful
if you have processed or edited exported
photos changing the file signature (size &
modification date). In this case, '--update'
would normally re-export the processed files
but with '--ignore-signature', files which
exist in the export directory will not be re-
exported. If used with '--sidecar', '--ignore-
signature' has the following behavior: 1) if
the metadata (in Photos) that went into the
sidecar did not change, the sidecar will not
be updated; 2) if the metadata (in Photos)
that went into the sidecar did change, a new
sidecar is written but a new image file is
not; 3) if a sidecar does not exist for the
photo, a sidecar will be written whether or
not the photo file was written or updated.
--only-new If used with --update, ignores any previously
exported files, even if missing from the
export folder and only exports new files that
haven't previously been exported.
--limit LIMIT Export at most LIMIT photos. Useful for
testing. May be used with --update to export
incrementally.
--dry-run Dry run (test) the export but don't actually
export any files; most useful with --verbose.
--export-as-hardlink Hardlink files instead of copying them. Cannot
be used with --exiftool which creates copies
of the files with embedded EXIF data. Note: on
APFS volumes, files are cloned when exporting
giving many of the same advantages as
hardlinks without having to use --export-as-
hardlink.
--touch-file Sets the file's modification time to match
photo date.
--overwrite Overwrite existing files. Default behavior is
to add (1), (2), etc to filename if file
already exists. Use this with caution as it
may create name collisions on export. (e.g. if
two files happen to have the same name)
--retry RETRY Automatically retry export up to RETRY times
if an error occurs during export. This may be
useful with network drives that experience
intermittent errors.
--export-by-date Automatically create output folders to
organize photos by date created (e.g.
DEST/2019/12/20/photoname.jpg).
--skip-edited Do not export edited version of photo if an
edited version exists.
--skip-original-if-edited Do not export original if there is an edited
version (exports only the edited version).
--skip-bursts Do not export all associated burst images in
the library if a photo is a burst photo.
--skip-live Do not export the associated live video
component of a live photo.
--skip-raw Do not export associated RAW image of a
RAW+JPEG pair. Note: this does not skip RAW
photos if the RAW photo does not have an
associated JPEG image (e.g. the RAW file was
imported to Photos without a JPEG preview).
--skip-uuid UUID Skip photos with UUID(s) during export. May be
repeated to include multiple UUIDs.
--skip-uuid-from-file FILE Skip photos with UUID(s) loaded from FILE.
Format is a single UUID per line. Lines
preceded with # are ignored.
--current-name Use photo's current filename instead of
original filename for export. Note: Starting
with Photos 5, all photos are renamed upon
import. By default, photos are exported with
the the original name they had before import.
--convert-to-jpeg Convert all non-JPEG images (e.g. RAW, HEIC,
PNG, etc) to JPEG upon export. Note: does not
convert the RAW component of a RAW+JPEG pair
as the associated JPEG image will be exported.
You can use --skip-raw to skip exporting the
associated RAW image of a RAW+JPEG pair. See
also --jpeg-quality and --jpeg-ext. Only works
if your Mac has a GPU (thus may not work on
virtual machines).
--jpeg-quality FLOAT RANGE Value in range 0.0 to 1.0 to use with
--convert-to-jpeg. A value of 1.0 specifies
best quality, a value of 0.0 specifies maximum
compression. Defaults to 1.0 [0.0<=x<=1.0]
--fix-orientation Automatically fix image orientation in
exported photos to match orientation in Photos
database. Requires exiftool be installed and
in the path. This is useful mainly for iPhoto
libraries. When an image is rotated in iPhoto,
the image orientation is not actually changed,
instead the image is tagged with an
orientation value in the iPhoto database. This
means that when the image is exported, the
orientation may not be correct. This option
will read the EXIF orientation data and fix
the image's orientation if necessary. If used
with Photos libraries, this option will result
in the original image also being adjusted upon
export.
--preview Export preview image generated by Photos. This
is a lower-resolution image used by Photos to
quickly preview the image. See also --preview-
suffix and --preview-if-missing.
--preview-if-missing Export preview image generated by Photos if
the actual photo file is missing from the
library. This may be helpful if photos were
not copied to the Photos library and the
original photo is missing. See also --preview-
suffix and --preview.
--preview-suffix SUFFIX Optional suffix template for naming preview
photos. Default name for preview photos is in
form 'photoname_preview.ext'. For example,
with '--preview-suffix _low_res', the preview
photo would be named 'photoname_low_res.ext'.
The default suffix is '_preview'. Multi-value
templates (see Templating System) are not
permitted with --preview-suffix. See also
--preview and --preview-if-missing.
--download-missing Attempt to download missing photos from
iCloud. The current implementation uses
Applescript to interact with Photos to export
the photo which will force Photos to download
from iCloud if the photo does not exist on
disk. This will be slow and will require
internet connection. This obviously only works
if the Photos library is synched to iCloud.
Note: --download-missing does not currently
export all burst images; only the primary
photo will be exported--associated burst
images will be skipped.
--export-aae Also export an adjustments file detailing
edits made to the original. The resulting file
is named photoname.AAE. Note that to import
these files back to Photos succesfully, you
also need to export the edited photo and match
the filename format Photos.app expects:
--filename 'IMG_{edited_version?E,}{id:04d}'
--edited-suffix ''
--sidecar FORMAT Create sidecar for each photo exported; valid
FORMAT values: xmp, json, exiftool; --sidecar
xmp: create XMP sidecar used by Digikam, Adobe
Lightroom, etc. The sidecar file is named in
format photoname.ext.xmp The XMP sidecar
exports the following tags: Description,
Title, Keywords/Tags, Subject (set to Keywords
+ PersonInImage), PersonInImage, CreateDate,
ModifyDate, GPSLongitude, Face Regions
(Metadata Working Group and Microsoft Photo).
--sidecar json: create JSON sidecar useable by
exiftool (https://exiftool.org/) The sidecar
file can be used to apply metadata to the file
with exiftool, for example: "exiftool
-j=photoname.jpg.json photoname.jpg" The
sidecar file is named in format
photoname.ext.json; format includes tag groups
(equivalent to running 'exiftool -G -j').
--sidecar exiftool: create JSON sidecar
compatible with output of 'exiftool -j'.
Unlike '--sidecar json', '--sidecar exiftool'
does not export tag groups. Sidecar filename
is in format photoname.ext.json; For a list of
tags exported in the JSON and exiftool
sidecar, see '--exiftool'. See also '--ignore-
signature'.
--sidecar-drop-ext Drop the photo's extension when naming sidecar
files. By default, sidecar files are named in
format 'photo_filename.photo_ext.sidecar_ext',
e.g. 'IMG_1234.JPG.xmp'. Use '--sidecar-drop-
ext' to ignore the photo extension. Resulting
sidecar files will have name in format
'IMG_1234.xmp'. Warning: this may result in
sidecar filename collisions if there are files
of different types but the same name in the
output directory, e.g. 'IMG_1234.JPG' and
'IMG_1234.MOV'.
--sidecar-template MAKO_TEMPLATE_FILE SIDECAR_FILENAME_TEMPLATE OPTIONS
Create a custom sidecar file for each photo
exported with user provided Mako template
(MAKO_TEMPLATE_FILE). MAKO_TEMPLATE_FILE must
be a valid Mako template (see
https://www.makotemplates.org/). The template
will passed the following variables: photo
(PhotoInfo object for the photo being
exported), sidecar_path (pathlib.Path object
for the path to the sidecar being written),
and photo_path (pathlib.Path object for the
path to the exported photo.
SIDECAR_FILENAME_TEMPLATE must be a valid
template string (see Templating System in
help) which will be rendered to generate the
filename of the sidecar file. The `{filepath}`
template variable may be used in the
SIDECAR_FILENAME_TEMPLATE to refer to the
filename of the photo being exported. OPTIONS
is a comma-separated list of strings providing
additional options to the template. Valid
options are: write_skipped, strip_whitespace,
strip_lines, skip_zero, catch_errors, none.
write_skipped will cause the sidecar file to
be written even if the photo is skipped during
export. If write_skipped is not passed as an
option, the sidecar file will not be written
if the photo is skipped during export.
strip_whitespace and strip_lines indicate
whether or not to strip whitespace and blank
lines, respectively, from the resulting
sidecar file. skip_zero causes the sidecar
file to be skipped if the rendered template is
zero-length. catch_errors causes errors in the
template to be caught and logged but not
raised. Without catch_errors, osxphotos will
abort the export if an error occurs in the
template. For example, to create a sidecar
file with extension .xmp using a template file
named 'sidecar.mako' and write a sidecar for
skipped photos and strip blank lines but not
whitespace: `--sidecar-template sidecar.mako
'{filepath}.xmp' write_skipped,strip_lines`.
To do the same but to drop the photo extension
from the sidecar filename: `--sidecar-template
sidecar.mako
'{filepath.parent}/{filepath.stem}.xmp'
write_skipped,strip_lines`. If you are not
passing any options, you must pass 'none' as
the last argument to --sidecar-template:
`--sidecar-template sidecar.mako
'{filepath}.xmp' none`. For an example Mako
file see https://raw.githubusercontent.com/Rhe
tTbull/osxphotos/main/examples/custom_sidecar.
mako
--exiftool Use exiftool to write metadata directly to
exported photos. To use this option, exiftool
must be installed and in the path. exiftool
may be installed from https://exiftool.org/.
Cannot be used with --export-as-hardlink.
Writes the following metadata:
EXIF:ImageDescription, XMP:Description (see
also --description-template); XMP:Title;
XMP:TagsList, IPTC:Keywords, XMP:Subject (see
also --keyword-template, --person-keyword,
--album-keyword); XMP:PersonInImage;
EXIF:GPSLatitudeRef; EXIF:GPSLongitudeRef;
EXIF:GPSLatitude; EXIF:GPSLongitude;
EXIF:GPSPosition; EXIF:DateTimeOriginal;
EXIF:OffsetTimeOriginal; EXIF:ModifyDate (see
--ignore-date-modified); IPTC:DateCreated;
IPTC:TimeCreated; (video files only):
QuickTime:CreationDate; QuickTime:CreateDate;
QuickTime:ModifyDate (see also --ignore-date-
modified); QuickTime:GPSCoordinates;
UserData:GPSCoordinates.
--exiftool-path EXIFTOOL_PATH Optionally specify path to exiftool; if not
provided, will look for exiftool in $PATH.
--exiftool-option OPTION Optional flag/option to pass to exiftool when
using --exiftool. For example, --exiftool-
option '-m' to ignore minor warnings. Specify
these as you would on the exiftool command
line. See exiftool docs at
https://exiftool.org/exiftool_pod.html for
full list of options. More than one option may
be specified by repeating the option, e.g.
--exiftool-option '-m' --exiftool-option '-F'.
--exiftool-merge-keywords Merge any keywords found in the original file
with keywords used for '--exiftool' and '--
sidecar'.
--exiftool-merge-persons Merge any persons found in the original file
with persons used for '--exiftool' and '--
sidecar'.
--favorite-rating When used with --exiftool or --sidecar, set
XMP:Rating=5 for photos marked as Favorite and
XMP:Rating=0 for non-Favorites. If not
specified, XMP:Rating is not set.
--ignore-date-modified If used with --exiftool or --sidecar, will
ignore the photo modification date and set
EXIF:ModifyDate to EXIF:DateTimeOriginal; this
is consistent with how Photos handles the
EXIF:ModifyDate tag.
--person-keyword Use person in image as keyword/tag when
exporting metadata.
--album-keyword Use album name as keyword/tag when exporting
metadata.
--keyword-template TEMPLATE For use with --exiftool, --sidecar; specify a
template string to use as keyword in the form
'{name,DEFAULT}' This is the same format as
--directory. For example, if you wanted to
add the full path to the folder and album
photo is contained in as a keyword when
exporting you could specify --keyword-template
"{folder_album}" You may specify more than one
template, for example --keyword-template
"{folder_album}" --keyword-template
"{created.year}". See '--replace-keywords' and
Templating System below.
--replace-keywords Replace keywords with any values specified
with --keyword-template. By default,
--keyword-template will add keywords to any
keywords already associated with the photo.
If --replace-keywords is specified, values
from --keyword-template will replace any
existing keywords instead of adding additional
keywords.
--description-template TEMPLATE
For use with --exiftool, --sidecar; specify a
template string to use as description in the
form '{name,DEFAULT}' This is the same format
as --directory. For example, if you wanted to
append 'exported with osxphotos on [today's
date]' to the description, you could specify
--description-template "{descr} exported with
osxphotos on {today.date}" See Templating
System below.
--finder-tag-template TEMPLATE Set MacOS Finder tags to TEMPLATE. These tags
can be searched in the Finder or Spotlight
with 'tag:tagname' format. For example, '--
finder-tag-template "{label}"' to set Finder
tags to photo labels. You may specify multiple
TEMPLATE values by using '--finder-tag-
template' multiple times. See also '--finder-
tag-keywords and Extended Attributes below.'.
--finder-tag-keywords Set MacOS Finder tags to keywords; any
keywords specified via '--keyword-template', '
--person-keyword', etc. will also be used as
Finder tags. See also '--finder-tag-template
and Extended Attributes below.'.
--xattr-template ATTRIBUTE TEMPLATE
Set extended attribute ATTRIBUTE to TEMPLATE
value. Valid attributes are: 'authors',
'comment', 'copyright', 'creator',
'description', 'findercomment', 'headline',
'participants', 'projects', 'starrating',
'subject', 'title', 'version'. For example, to
set Finder comment to the photo's title and
description: '--xattr-template findercomment
"{title}; {descr}" See Extended Attributes
below for additional details on this option.
--directory DIRECTORY Optional template for specifying name of
output directory in the form '{name,DEFAULT}'.
See below for additional details on templating
system.
--filename FILENAME Optional template for specifying name of
output file in the form '{name,DEFAULT}'. File
extension will be added automatically--do not
include an extension in the FILENAME template.
See below for additional details on templating
system.
--jpeg-ext EXTENSION Specify file extension for JPEG files. Photos
uses .jpeg for edited images but many images
are imported with .jpg or .JPG which can
result in multiple different extensions used
for JPEG files upon export. Use --jpeg-ext to
specify a single extension to use for all
exported JPEG images. Valid values are jpeg,
jpg, JPEG, JPG; e.g. '--jpeg-ext jpg' to use
'.jpg' for all JPEGs.
--strip Optionally strip leading and trailing
whitespace from any rendered templates. For
example, if --filename template is "{title,}
{original_name}" and image has no title,
resulting file would have a leading space but
if used with --strip, this will be removed.
--edited-suffix SUFFIX Optional suffix template for naming edited
photos. Default name for edited photos is in
form 'photoname_edited.ext'. For example, with
'--edited-suffix _bearbeiten', the edited
photo would be named
'photoname_bearbeiten.ext'. The default
suffix is '_edited'. Multi-value templates
(see Templating System) are not permitted with
--edited-suffix.
--original-suffix SUFFIX Optional suffix template for naming original
photos. Default name for original photos is
in form 'filename.ext'. For example, with '--
original-suffix _original', the original photo
would be named 'filename_original.ext'. The
default suffix is '' (no suffix). Multi-value
templates (see Templating System) are not
permitted with --original-suffix.
--use-photos-export Force the use of AppleScript or PhotoKit to
export even if not missing (see also '--
download-missing' and '--use-photokit').
--use-photokit Use with '--download-missing' or '--use-
photos-export' to use direct Photos interface
instead of AppleScript to export. Highly
experimental alpha feature; does not work with
iTerm2 (use with Terminal.app). This is faster
and more reliable than the default AppleScript
interface.
--report REPORT_FILE Write a report of all files that were
exported. The extension of the report filename
will be used to determine the format. Valid
extensions are: .csv (CSV file), .json (JSON),
.db and .sqlite (SQLite database). REPORT_FILE
may be a template string (see Templating
System), for example, --report
'export_{today.date}.csv' will write a CSV
report file named with today's date. See also
--append.
--append If used with --report, add data to existing
report file instead of overwriting it. See
also --report.
--cleanup Cleanup export directory by deleting any files
which were not included in this export set.
For example, photos which had previously been
exported and were subsequently deleted in
Photos. WARNING: --cleanup will delete *any*
files in the export directory that were not
exported by osxphotos, for example, your own
scripts or other files. Be sure this is what
you intend before using --cleanup. Use --dry-
run with --cleanup first if you're not
certain. To prevent files not generated by
osxphotos from being deleted, you may specify
one or more rules in a file named
`.osxphotos_keep` in the export directory.
This file uses the same format as a .gitignore
file and should contain one rule per line;
lines starting with a `#` will be ignored.
Reference https://git-
scm.com/docs/gitignore#_pattern_format for
details. In addition to the standard
.gitignore rules, the rules may also be the
absolute path to a file or directory. For
example if export destination is
`/Volumes/Photos` and you want to keep all
`.txt` files, in the top level of the export
directory, you can specify `/*.txt"` in the
.osxphotos_keep file. If you want to keep all
`.txt` files in the export directory and all
subdirectories, you can specify `**/*.txt`. If
present, the .osxphotos_keep file will be read
after the export is completed and any rules
found in the file will be added to the list of
rules to keep. See also --keep.
--keep KEEP_RULE When used with --cleanup, prevents file or
directory matching KEEP_RULE from being
deleted when cleanup is run. Use this if there
are files in the export directory that you
don't want to be deleted when --cleanup is
run. KEEP_RULE follows the same format rules a
.gitignore file. Reference https://git-
scm.com/docs/gitignore#_pattern_format for
details. In addition to the standard
.gitignore rules, KEEP_RULE may also be the
absolute path to a file or directory. For
example if export destination is
`/Volumes/Photos` and you want to keep all
`.txt` files, in the top level of the export
directory, you can specify `--keep "/*.txt"`.
If you want to keep all `.txt` files in the
export directory and all subdirectories, you
can specify `--keep "**/*.txt"`. If wild card
is used, KEEP_RULE must be enclosed in quotes
to prevent the shell from expanding the
wildcard. --keep may be repeated to keep
additional files/directories. Rules may also
be included in a file named `.osxphotos_keep`
in the export directory. If present, this file
will be read after the export is completed and
any rules found in the file will be added to
the list of rules to keep. This file uses the
same format as a .gitignore file and should
contain one rule per line; lines starting with
a `#` will be ignored.
--add-exported-to-album ALBUM Add all exported photos to album ALBUM in
Photos. Album ALBUM will be created if it
doesn't exist. All exported photos will be
added to this album. This only works if the
Photos library being exported is the last-
opened (default) library in Photos.
--add-skipped-to-album ALBUM Add all skipped photos to album ALBUM in
Photos. Album ALBUM will be created if it
doesn't exist. All skipped photos will be
added to this album. This only works if the
Photos library being exported is the last-
opened (default) library in Photos.
--add-missing-to-album ALBUM Add all missing photos to album ALBUM in
Photos. Album ALBUM will be created if it
doesn't exist. All missing photos will be
added to this album. This only works if the
Photos library being exported is the last-
opened (default) library in Photos.
--post-command CATEGORY COMMAND
Run COMMAND on exported files of category
CATEGORY. CATEGORY can be one of: exported,
new, updated, skipped, missing, exif_updated,
touched, converted_to_jpeg,
sidecar_json_written, sidecar_json_skipped,
sidecar_exiftool_written,
sidecar_exiftool_skipped, sidecar_xmp_written,
sidecar_xmp_skipped, error. COMMAND is an
osxphotos template string, for example: '--
post-command exported "echo
{filepath|shell_quote} >>
{export_dir}/exported.txt"', which appends the
full path of all exported files to the file
'exported.txt'. You can run more than one
command by repeating the '--post-command'
option with different arguments. See also
--post-command-error and --post-function.See
Post Command below.
--post-command-error ACTION Specify either `continue` or `break` for
ACTION to control behavior when a post-command
fails. If `continue`, osxphotos will log the
error and continue processing. If `break`,
osxphotos will stop processing any additional
--post-command commands for the current photo
but will continue with the export. Without
--post-command-error, osxphotos will abort the
export if a post-command encounters an error.
--post-function filename.py::function
Run function on exported files. Use this in
format: --post-function filename.py::function
where filename.py is a python file you've
created and function is the name of the
function in the python file you want to call.
The function will be passed information about
the photo that's been exported and a list of
all exported files associated with the photo.
You can run more than one function by
repeating the '--post-function' option with
different arguments. You may also specify a
post function using a URL in format --post-
function 'https://path/to/module.py::function'
See Post Function below.
--exportdb EXPORTDB_FILE Specify alternate path for database file which
stores state information for export and
--update. If --exportdb is not specified,
export database will be saved to
'.osxphotos_export.db' in the export
directory. If --exportdb is specified, it
will be saved to the specified file.
--ramdb Copy export database to memory during export;
will improve performance when exporting over a
network or slow disk. See also --checkpoint.
--checkpoint NUMBER_OF_PHOTOS When used with --ramdb, periodically save the
export database back to disk after processing
NUMBER_OF_PHOTOS. When using --ramdb, the
export database will be automatically saved if
there is a crash or interrupt thus you do not
generally need to specify --checkpoint and
doing so may slow down the export if your
export database is large. This is an advanced
feature for those who need to fine-tune the
behavior of osxphotos. [x>=0]
-F, --ignore-exportdb If exporting to a directory that already
contains an export database and --update is
not specified, do not prompt to continue but
instead continue the export. Normally, if you
export to a directory that already contains an
export database and do not specify --update,
osxphotos will prompt you to continue. This is
because you may be inadvertently merging two
export sets. Use --ignore-exportdb to skip
this prompt and continue the export. The
resulting export database will contain the
combined state of both export sets. Short
option is '-F' (mnemonic: force export). See
also --update.
--no-exportdb Do not create an export database. This exports
all photos in the export set but does not save
any state information in the osxphotos export
database. If you use --no-exportdb, you will
not be able to use --update on subsequent
exports. It is recommended that you do not use
this option unless you are certain you
understand the implications.
--tmpdir DIR Specify alternate temporary directory. Default
is system temporary directory. osxphotos needs
to create a number of temporary files during
export. In some cases, particularly if the
Photos library is on an APFS volume that is
not the system volume, osxphotos may run
faster if you specify a temporary directory on
the same volume as the Photos library.
--alt-copy Use alternate copy method that may be more
reliable for some network attached storage
(NAS) devices. Use --alt-copy if you
experience problems exporting to a NAS device
or SMB volume. Unlike the default copy method,
--alt-copy does not support copy-on-write on
APFS volumes nor does it preserve filesystem
metadata.
--alt-db PATH Specify alternate path to Photos library
database. This is an advanced feature you
probably don't need. This may be useful when
exporting from a library on a very slow
external disk. In this case, you could copy
the `/database` folder from the Photos library
to the internal diskand use `--alt-db` to
specify the path to the database file on the
internal disk. then use `--library` to specify
the path to the Photos library root on the
external disk. For example: `--library
/Volumes/ExternalDisk/Photos.photoslibrary
--alt-db /path/to/database/Photos.sqlite`
--load-config CONFIG_FILE Load options from file as written with --save-
config. This allows you to save a complex
export command to file for later reuse. For
example: 'osxphotos export <lots of options
here> --save-config osxphotos.toml' then
'osxphotos export /path/to/export --load-
config osxphotos.toml'. If any other command
line options are used in conjunction with
--load-config, they will override the
corresponding values in the config file.
--save-config CONFIG_FILE Save options to file for use with --load-
config. File format is TOML. See also
--config-only.
--config-only If specified, saves the config file but does
not export any files; must be used with
--save-config.
--print TEMPLATE Render TEMPLATE string for each photo being
exported and print to stdout. TEMPLATE is an
osxphotos template string. This may be useful
for creating custom reports, etc. TEMPLATE
will be printed after the photo is exported or
skipped. May be repeated to print multiple
template strings.
--theme THEME Specify the color theme to use for output.
Valid themes are 'dark', 'light', 'mono', and
'plain'. Defaults to 'dark' or 'light'
depending on system dark mode setting.
-h, --help Show this message and exit.
Export
When exporting photos, osxphotos creates a database in the top-level export
folder called '.osxphotos_export.db'. This database preserves state
information used for determining which files need to be updated when run with
--update. It is recommended that if you later move the export folder tree you
also move the database file.
The --update option will only copy new or updated files from the library to
the export folder. If a file is changed in the export folder (for example,
you edited the exported image), osxphotos will detect this as a difference and
re-export the original image from the library thus overwriting the changes.
If using --update, the exported library should be treated as a backup, not a
working copy where you intend to make changes. If you do edit or process the
exported files and do not want them to be overwritten withsubsequent --update,
use --ignore-signature which will match filename but not file signature when
exporting.
Note: The number of files reported for export and the number actually exported
may differ due to live photos, associated raw images, and edited photos which
are reported in the total photos exported.
Implementation note: To determine which files need to be updated, osxphotos
stores file signature information in the '.osxphotos_export.db' database. The
signature includes size, modification time, and filename. In order to
minimize run time, --update does not do a full comparison (diff) of the files
nor does it compare hashes of the files. In normal usage, this is sufficient
for updating the library. You can always run export without the --update
option to re-export the entire library thus rebuilding the
'.osxphotos_export.db' database.
Extended Attributes
Some options (currently '--finder-tag-template', '--finder-tag-keywords',
'-xattr-template') write additional metadata accessible by Spotlight
to facilitate searching. For example, --finder-tag-keyword writes all
keywords (including any specified by '--keyword-template' or other
options) to Finder tags that are searchable in Spotlight using the syntax:
'tag:tagname'. For example, if you have images with keyword "Travel"
then using '--finder-tag-keywords' you could quickly find those images
in the Finder by typing 'tag:Travel' in the Spotlight search bar.
Finder tags are written to the 'com.apple.metadata:_kMDItemUserTags'
extended attribute. Unlike EXIF metadata, extended attributes do not
modify the actual file; the metadata is written to extended attributes
associated with the file and the Spotlight metadata database. Most
cloud storage services do not synch extended attributes. Dropbox does
sync them and any changes to a file's extended attributes will cause
Dropbox to re-sync the files.
The following attributes may be used with '--xattr-template':
Attribute Description
authors kMDItemAuthors; com.apple.metadata:kMDItemAuthors; The
author, or authors, of the contents of the file.; list of
strings
comment kMDItemComment; com.apple.metadata:kMDItemComment; A comment
related to the file. This differs from the Finder comment,
kMDItemFinderComment.; string
copyright kMDItemCopyright; com.apple.metadata:kMDItemCopyright; The
copyright owner of the file contents.; string
creator kMDItemCreator; com.apple.metadata:kMDItemCreator;
Application used to create the document content (for example
"Word", "Pages", and so on).; string
description kMDItemDescription; com.apple.metadata:kMDItemDescription; A
description of the content of the resource. The description
may include an abstract, table of contents, reference to a
graphical representation of content or a free-text account of
the content.; string
findercomment kMDItemFinderComment;
com.apple.metadata:kMDItemFinderComment; Finder comments for
this file.; string
headline kMDItemHeadline; com.apple.metadata:kMDItemHeadline; A
publishable entry providing a synopsis of the contents of the
file. For example, "Apple Introduces the iPod Photo".; string
participants kMDItemParticipants; com.apple.metadata:kMDItemParticipants;
The list of people who are visible in an image or movie or
written about in a document.; list of strings
projects kMDItemProjects; com.apple.metadata:kMDItemProjects; The list
of projects that this file is part of. For example, if you
were working on a movie all of the files could be marked as
belonging to the project "My Movie".; list of strings
starrating kMDItemStarRating; com.apple.metadata:kMDItemStarRating; User
rating of this item. For example, the stars rating of an
iTunes track.; number
subject kMDItemSubject; com.apple.metadata:kMDItemSubject; Subject of
the this item.; string
title kMDItemTitle; com.apple.metadata:kMDItemTitle; The title of
the file. For example, this could be the title of a document,
the name of a song, or the subject of an email message.;
string
version kMDItemVersion; com.apple.metadata:kMDItemVersion; The
version number of this file.; string
For additional information on extended attributes see: https://developer.apple
.com/documentation/coreservices/file_metadata/mditem/common_metadata_attribute
_keys
Templating System
The templating system converts one or template statements, written in
osxphotos metadata templating language, to one or more rendered values using
information from the photo being processed.
In its simplest form, a template statement has the form: "{template_field}",
for example "{title}" which would resolve to the title of the photo.
Template statements may contain one or more modifiers. The full syntax is:
"pretext{delim+template_field:subfield(field_arg)|filter[find,replace]
conditional&combine_value?bool_value,default}posttext"
Template statements are white-space sensitive meaning that white space
(spaces, tabs) changes the meaning of the template statement.
pretext and posttext are free form text. For example, if a photo has title
"My Photo Title" the template statement "The title of the photo is {title}",
resolves to "The title of the photo is My Photo Title". The pretext in this
example is "The title if the photo is " and the template_field is {title}.
delim: optional delimiter string to use when expanding multi-valued template
values in-place
+: If present before template name, expands the template in place. If delim
not provided, values are joined with no delimiter.
e.g. if Photo keywords are ["foo","bar"]:
• "{keyword}" renders to "foo", "bar"
• "{,+keyword}" renders to: "foo,bar"
• "{; +keyword}" renders to: "foo; bar"
• "{+keyword}" renders to "foobar"
template_field: The template field to resolve. See Template Substitutions for
full list of template fields.
:subfield: Some templates have sub-fields, For example, {exiftool:IPTC:Make};
the template_field is exiftool and the sub-field is IPTC:Make.
(field_arg): optional arguments to pass to the field; for example, with
{folder_album} this is used to pass the path separator used for joining
folders and albums when rendering the field (default is "/" for
{folder_album}).
|filter: You may optionally append one or more filter commands to the end of
the template field using the vertical pipe ('|') symbol. Filters may be
combined, separated by '|' as in: {keyword|capitalize|parens}.
Valid filters are:
• lower: Convert value to lower case, e.g. 'Value' => 'value'.
• upper: Convert value to upper case, e.g. 'Value' => 'VALUE'.
• strip: Strip whitespace from beginning/end of value, e.g. ' Value ' =>
'Value'.
• titlecase: Convert value to title case, e.g. 'my value' => 'My Value'.
• capitalize: Capitalize first word of value and convert other words to lower
case, e.g. 'MY VALUE' => 'My value'.
• braces: Enclose value in curly braces, e.g. 'value => '{value}'.
• parens: Enclose value in parentheses, e.g. 'value' => '(value')
• brackets: Enclose value in brackets, e.g. 'value' => '[value]'
• shell_quote: Quotes the value for safe usage in the shell, e.g. My
file.jpeg => 'My file.jpeg'; only adds quotes if needed.
• function: Run custom python function to filter value; use in format
'function:/path/to/file.py::function_name'. See example at
https://github.com/RhetTbull/osxphotos/blob/master/examples/template_filter
.py
• split(x): Split value into a list of values using x as delimiter, e.g.
'value1;value2' => ['value1', 'value2'] if used with split(;).
• autosplit: Automatically split delimited string into separate values; will
split strings delimited by comma, semicolon, or space, e.g. 'value1,value2'
=> ['value1', 'value2'].
• chop(x): Remove x characters off the end of value, e.g. chop(1): 'Value' =>
'Valu'; when applied to a list, chops characters from each list value, e.g.
chop(1): ['travel', 'beach']=> ['trave', 'beac'].
• chomp(x): Remove x characters from the beginning of value, e.g. chomp(1):
['Value'] => ['alue']; when applied to a list, removes characters from each
list value, e.g. chomp(1): ['travel', 'beach']=> ['ravel', 'each'].
• sort: Sort list of values, e.g. ['c', 'b', 'a'] => ['a', 'b', 'c'].
• rsort: Sort list of values in reverse order, e.g. ['a', 'b', 'c'] => ['c',
'b', 'a'].
• reverse: Reverse order of values, e.g. ['a', 'b', 'c'] => ['c', 'b', 'a'].
• uniq: Remove duplicate values, e.g. ['a', 'b', 'c', 'b', 'a'] => ['a', 'b',
'c'].
• join(x): Join list of values with delimiter x, e.g. join(,): ['a', 'b',
'c'] => 'a,b,c'; the DELIM option functions similar to join(x) but with
DELIM, the join happens before being passed to any filters.May optionally
be used without an argument, that is 'join()' which joins values together
with no delimiter. e.g. join(): ['a', 'b', 'c'] => 'abc'.
• append(x): Append x to list of values, e.g. append(d): ['a', 'b', 'c'] =>
['a', 'b', 'c', 'd'].
• prepend(x): Prepend x to list of values, e.g. prepend(d): ['a', 'b', 'c']
=> ['d', 'a', 'b', 'c'].
• appends(x): Append s[tring] Append x to each value of list of values, e.g.
appends(d): ['a', 'b', 'c'] => ['ad', 'bd', 'cd'].
• prepends(x): Prepend s[tring] x to each value of list of values, e.g.
prepends(d): ['a', 'b', 'c'] => ['da', 'db', 'dc'].
• remove(x): Remove x from list of values, e.g. remove(b): ['a', 'b', 'c'] =>
['a', 'c'].
• slice(start:stop:step): Slice list using same semantics as Python's list
slicing, e.g. slice(1:3): ['a', 'b', 'c', 'd'] => ['b', 'c']; slice(1:4:2):
['a', 'b', 'c', 'd'] => ['b', 'd']; slice(1:): ['a', 'b', 'c', 'd'] =>
['b', 'c', 'd']; slice(:-1): ['a', 'b', 'c', 'd'] => ['a', 'b', 'c'];
slice(::-1): ['a', 'b', 'c', 'd'] => ['d', 'c', 'b', 'a']. See also
sslice().
• sslice(start:stop:step): [s(tring) slice] Slice values in a list using same
semantics as Python's string slicing, e.g. sslice(1:3):'abcd => 'bc';
sslice(1:4:2): 'abcd' => 'bd', etc. See also slice().
• filter(x): Filter list of values using predicate x; for example,
{folder_album|filter(contains Events)} returns only folders/albums
containing the word 'Events' in their path.
• int: Convert values in list to integer, e.g. 1.0 => 1. If value cannot be
converted to integer, remove value from list. ['1.1', 'x'] => ['1']. See
also float.
• float: Convert values in list to floating point number, e.g. 1 => 1.0. If
value cannot be converted to float, remove value from list. ['1', 'x'] =>
['1.0']. See also int.
e.g. if Photo keywords are ["FOO","bar"]:
• "{keyword|lower}" renders to "foo", "bar"
• "{keyword|upper}" renders to: "FOO", "BAR"
• "{keyword|capitalize}" renders to: "Foo", "Bar"
• "{keyword|lower|parens}" renders to: "(foo)", "(bar)"
e.g. if Photo description is "my description":
• "{descr|titlecase}" renders to: "My Description"
e.g. If Photo is in Album1 in Folder1:
• "{folder_album}" renders to ["Folder1/Album1"]
• "{folder_album(>)}" renders to ["Folder1>Album1"]
• "{folder_album()}" renders to ["Folder1Album1"]
[find,replace]: optional text replacement to perform on rendered template
value. For example, to replace "/" in an album name, you could use the
template "{album[/,-]}". Multiple replacements can be made by appending "|"
and adding another find|replace pair. e.g. to replace both "/" and ":" in
album name: "{album[/,-|:,-]}". find/replace pairs are not limited to single
characters. The "|" character cannot be used in a find/replace pair.
conditional: optional conditional expression that is evaluated as boolean
(True/False) for use with the ?bool_value modifier. Conditional expressions
take the form 'not operator value' where not is an optional modifier that
negates the operator. Note: the space before the conditional expression is
required if you use a conditional expression. Valid comparison operators are:
• contains: template field contains value, similar to python's in
• matches: template field contains exactly value, unlike contains: does not
match partial matches
• startswith: template field starts with value
• endswith: template field ends with value
• <=: template field is less than or equal to value
• >=: template field is greater than or equal to value
• <: template field is less than value
• >: template field is greater than value
• ==: template field equals value
• !=: template field does not equal value
The value part of the conditional expression is treated as a bare (unquoted)
word/phrase. Multiple values may be separated by '|' (the pipe symbol).
value is itself a template statement so you can use one or more template
fields in value which will be resolved before the comparison occurs.
For example:
• {keyword matches Beach} resolves to True if 'Beach' is a keyword. It would
not match keyword 'BeachDay'.
• {keyword contains Beach} resolves to True if any keyword contains the word
'Beach' so it would match both 'Beach' and 'BeachDay'.
• {photo.score.overall > 0.7} resolves to True if the photo's overall
aesthetic score is greater than 0.7.
• {keyword|lower contains beach} uses the lower case filter to do
case-insensitive matching to match any keyword that contains the word
'beach'.
• {keyword|lower not contains beach} uses the not modifier to negate the
comparison so this resolves to True if there is no keyword that matches
'beach'.
Examples: to export photos that contain certain keywords with the osxphotos
export command's --directory option:
--directory "{keyword|lower matches
travel|vacation?Travel-Photos,Not-Travel-Photos}"
This exports any photo that has keywords 'travel' or 'vacation' into a
directory 'Travel-Photos' and all other photos into directory
'Not-Travel-Photos'.
This can be used to rename files as well, for example: --filename
"{favorite?Favorite-{original_name},{original_name}}"
This renames any photo that is a favorite as 'Favorite-ImageName.jpg' (where
'ImageName.jpg' is the original name of the photo) and all other photos with
the unmodified original name.
&combine_value: Template fields may be combined with another template
statement to return multiple values. The combine_value is another template
statement. For example, the template {created.year&{folder_album,}} would
resolve to ["1999", "Vacation"] if the photo was created in 1999 and was in
the album Vacation. Because the combine_value is a template statement,
multiple templates may be combined together by nesting the combine operator:
{template1&{template2&{template3,},},}. In this example, a null default value
is used to prevent the default value from being combined if any of the nested
templates does not resolve to a value
?bool_value: Template fields may be evaluated as boolean (True/False) by
appending "?" after the field name (and following "(field_arg)" or
"[find/replace]". If a field is True (e.g. photo is HDR and field is "{hdr}")
or has any value, the value following the "?" will be used to render the
template instead of the actual field value. If the template field evaluates
to False (e.g. in above example, photo is not HDR) or has no value (e.g. photo
has no title and field is "{title}") then the default value following a ","
will be used.
e.g. if photo is an HDR image,
• "{hdr?ISHDR,NOTHDR}" renders to "ISHDR"
and if it is not an HDR image,
• "{hdr?ISHDR,NOTHDR}" renders to "NOTHDR"
,default: optional default value to use if the template name has no value.
This modifier is also used for the value if False for boolean-type fields (see
above) as well as to hold a sub-template for values like {created.strftime}.
If no default value provided, "_" is used.
e.g., if photo has no title set,
• "{title}" renders to "_"
• "{title,I have no title}" renders to "I have no title"
Template fields such as created.strftime use the default value to pass the
template to use for strftime.
e.g., if photo date is 4 February 2020, 19:07:38,
• "{created.strftime,%Y-%m-%d-%H%M%S}" renders to "2020-02-04-190738"
Some template fields such as "{media_type}" use the default value to allow
customization of the output. For example, "{media_type}" resolves to the
special media type of the photo such as panorama or selfie. You may use the
default value to override these in form:
"{media_type,video=vidéo;time_lapse=vidéo_accélérée}". In this example, if
photo was a time_lapse photo, media_type would resolve to vidéo_accélérée
instead of time_lapse.
Either or both bool_value or default (False value) may be empty which would
result in empty string "" when rendered.
If you want to include "{" or "}" in the output, use "{openbrace}" or
"{closebrace}" template substitution.
e.g. "{created.year}/{openbrace}{title}{closebrace}" would result in
"2020/{Photo Title}".
Variables
You can define variables for later use in the template string using the format
{var:NAME,VALUE} where VALUE is a template statement. Variables may then be
referenced using the format %NAME. For example: {var:foo,bar} defines the
variable %foo to have value bar. This can be useful if you want to re-use a
complex template value in multiple places within your template string or for
allowing the use of characters that would otherwise be prohibited in a
template string. For example, the "pipe" (|) character is not allowed in a
find/replace pair but you can get around this limitation like so:
{var:pipe,{pipe}}{title[-,%pipe]} which replaces the - character with | (the
value of %pipe).
Another use case for variables is filtering combined template values. For
example, using the &combine_value mechanism to combine two template values
that might result in duplicate values, you could do the following:
{var:myvar,{template1&{template2,},}}{%myvar|uniq} which allows the use of the
uniq filter against the combined template values.
Variables can also be referenced as fields in the template string, for
example: {var:year,{created.year}}{original_name}-{%year}. In some cases, use
of variables can make your template string more readable. Variables can be
used as template fields, as values for filters, as values for conditional
operations, or as default values. When used as a conditional value or default
value, variables should be treated like any other field and enclosed in braces
as conditional and default values are evaluated as template strings. For
example: {var:name,Katie}{person contains {%name}?{%name},Not-{%name}}.
If you need to use a % (percent sign character), you can escape the percent
sign by using %%. You can also use the {percent} template field where a
template field is required. For example:
{title[:,%%]} replaces the : with % and {title contains
Foo?{title}{percent},{title}} adds % to the title if it contains Foo.
With the --directory and --filename options you may specify a template for the
export directory or filename, respectively. The directory will be appended to
the export path specified in the export DEST argument to export. For example,
if template is '{created.year}/{created.month}', and export destination DEST
is '/Users/maria/Pictures/export', the actual export directory for a photo
would be '/Users/maria/Pictures/export/2020/March' if the photo was created in
March 2020.
The templating system may also be used with the --keyword-template option to
set keywords on export (with --exiftool or --sidecar), for example, to set a
new keyword in format 'folder/subfolder/album' to preserve the folder/album
structure, you can use --keyword-template "{folder_album}" or in the
'folder>subfolder>album' format used in Lightroom Classic, --keyword-template
"{folder_album(>)}".
In the template, valid template substitutions will be replaced by the
corresponding value from the table below. Invalid substitutions will result
in a an error and the script will abort.
Template Substitutions
Substitution Description
{name} Current filename of the photo
{original_name} Photo's original filename when imported to
Photos
{title} Title of the photo
{descr} Description of the photo
{media_type} Special media type resolved in this
precedence: selfie, time_lapse, panorama,
slow_mo, screenshot, screen_recording,
portrait, live_photo, burst, photo, video.
Defaults to 'photo' or 'video' if no special
type. Customize one or more media types
using format: '{media_type,video=vidéo;time_
lapse=vidéo_accélérée}'
{photo_or_video} 'photo' or 'video' depending on what type
the image is. To customize, use default
value as in
'{photo_or_video,photo=fotos;video=videos}'
{hdr} Photo is HDR?; True/False value, use in
format '{hdr?VALUE_IF_TRUE,VALUE_IF_FALSE}'
{edited} True if photo has been edited (has
adjustments), otherwise False; use in format
'{edited?VALUE_IF_TRUE,VALUE_IF_FALSE}'
{edited_version} True if template is being rendered for the
edited version of a photo, otherwise False.
{favorite} Photo has been marked as favorite?;
True/False value, use in format
'{favorite?VALUE_IF_TRUE,VALUE_IF_FALSE}'
{created} Photo's creation date in ISO format, e.g.
'2020-03-22'
{created.date} Photo's creation date in ISO format, e.g.
'2020-03-22'
{created.year} 4-digit year of photo creation time
{created.yy} 2-digit year of photo creation time
{created.mm} 2-digit month of the photo creation time
(zero padded)
{created.month} Month name in user's locale of the photo
creation time
{created.mon} Month abbreviation in the user's locale of
the photo creation time
{created.dd} 2-digit day of the month (zero padded) of
photo creation time
{created.dow} Day of week in user's locale of the photo
creation time
{created.doy} 3-digit day of year (e.g Julian day) of
photo creation time, starting from 1 (zero
padded)
{created.hour} 2-digit hour of the photo creation time
{created.min} 2-digit minute of the photo creation time
{created.sec} 2-digit second of the photo creation time
{created.strftime} Apply strftime template to file creation
date/time. Should be used in form
{created.strftime,TEMPLATE} where TEMPLATE
is a valid strftime template, e.g.
{created.strftime,%Y-%U} would result in
year-week number of year: '2020-23'. If used
with no template will return null value. See
https://strftime.org/ for help on strftime
templates.
{modified} Photo's modification date in ISO format,
e.g. '2020-03-22'; uses creation date if
photo is not modified
{modified.date} Photo's modification date in ISO format,
e.g. '2020-03-22'; uses creation date if
photo is not modified
{modified.year} 4-digit year of photo modification time;
uses creation date if photo is not modified
{modified.yy} 2-digit year of photo modification time;
uses creation date if photo is not modified
{modified.mm} 2-digit month of the photo modification time
(zero padded); uses creation date if photo
is not modified
{modified.month} Month name in user's locale of the photo
modification time; uses creation date if
photo is not modified
{modified.mon} Month abbreviation in the user's locale of
the photo modification time; uses creation
date if photo is not modified
{modified.dd} 2-digit day of the month (zero padded) of
the photo modification time; uses creation
date if photo is not modified
{modified.dow} Day of week in user's locale of the photo
modification time; uses creation date if
photo is not modified
{modified.doy} 3-digit day of year (e.g Julian day) of
photo modification time, starting from 1
(zero padded); uses creation date if photo
is not modified
{modified.hour} 2-digit hour of the photo modification time;
uses creation date if photo is not modified
{modified.min} 2-digit minute of the photo modification
time; uses creation date if photo is not
modified
{modified.sec} 2-digit second of the photo modification
time; uses creation date if photo is not
modified
{modified.strftime} Apply strftime template to file modification
date/time. Should be used in form
{modified.strftime,TEMPLATE} where TEMPLATE
is a valid strftime template, e.g.
{modified.strftime,%Y-%U} would result in
year-week number of year: '2020-23'. If used
with no template will return null value.
Uses creation date if photo is not modified.
See https://strftime.org/ for help on
strftime templates.
{today} Current date in iso format, e.g.
'2020-03-22'
{today.date} Current date in iso format, e.g.
'2020-03-22'
{today.year} 4-digit year of current date
{today.yy} 2-digit year of current date
{today.mm} 2-digit month of the current date (zero
padded)
{today.month} Month name in user's locale of the current
date
{today.mon} Month abbreviation in the user's locale of
the current date
{today.dd} 2-digit day of the month (zero padded) of
current date
{today.dow} Day of week in user's locale of the current
date
{today.doy} 3-digit day of year (e.g Julian day) of
current date, starting from 1 (zero padded)
{today.hour} 2-digit hour of the current date
{today.min} 2-digit minute of the current date
{today.sec} 2-digit second of the current date
{today.strftime} Apply strftime template to current
date/time. Should be used in form
{today.strftime,TEMPLATE} where TEMPLATE is
a valid strftime template, e.g.
{today.strftime,%Y-%U} would result in year-
week number of year: '2020-23'. If used with
no template will return null value. See
https://strftime.org/ for help on strftime
templates.
{place.name} Place name from the photo's reverse
geolocation data, as displayed in Photos
{place.country_code} The ISO country code from the photo's
reverse geolocation data
{place.name.country} Country name from the photo's reverse
geolocation data
{place.name.state_province} State or province name from the photo's
reverse geolocation data
{place.name.city} City or locality name from the photo's
reverse geolocation data
{place.name.area_of_interest} Area of interest name (e.g. landmark or
public place) from the photo's reverse
geolocation data
{place.address} Postal address from the photo's reverse
geolocation data, e.g. '2007 18th St NW,
Washington, DC 20009, United States'
{place.address.street} Street part of the postal address, e.g.
'2007 18th St NW'
{place.address.city} City part of the postal address, e.g.
'Washington'
{place.address.state_province} State/province part of the postal address,
e.g. 'DC'
{place.address.postal_code} Postal code part of the postal address, e.g.
'20009'
{place.address.country} Country name of the postal address, e.g.
'United States'
{place.address.country_code} ISO country code of the postal address, e.g.
'US'
{searchinfo.season} Season of the year associated with a photo,
e.g. 'Summer'; (Photos 5+ only, applied
automatically by Photos' image
categorization algorithms).
{exif.camera_make} Camera make from original photo's EXIF
information as imported by Photos, e.g.
'Apple'
{exif.camera_model} Camera model from original photo's EXIF
information as imported by Photos, e.g.
'iPhone 6s'
{exif.lens_model} Lens model from original photo's EXIF
information as imported by Photos, e.g.
'iPhone 6s back camera 4.15mm f/2.2'
{moment} The moment title of the photo
{uuid} Photo's internal universally unique
identifier (UUID) for the photo, a
36-character string unique to the photo,
e.g. '128FB4C6-0B16-4E7D-9108-FB2E90DA1546'
{shortuuid} A shorter representation of photo's internal
universally unique identifier (UUID) for the
photo, a 22-character string unique to the
photo, e.g. 'JYsxugP9UjetmCbBCHXcmu'
{id} A unique number for the photo based on its
primary key in the Photos database. A
sequential integer, e.g. 1, 2, 3...etc.
Each asset associated with a photo (e.g. an
image and Live Photo preview) will share the
same id. May be formatted using a python
string format code. For example, to format
as a 5-digit integer and pad with zeros, use
'{id:05d}' which results in 00001, 00002,
00003...etc.
{counter} A sequential counter, starting at 0, that
increments each time it is evaluated.To
start counting at a value other than 0,
append append '(starting_value)' to the
field name.For example, to start counting at
1 instead of 0: '{counter(1)}'.May be
formatted using a python string format
code.For example, to format as a 5-digit
integer and pad with zeros, use
'{counter:05d(1)}'which results in 00001,
00002, 00003...etc.You may also specify a
stop value which causes the counter to reset
to the starting valuewhen the stop value is
reached and a step size which causes the
counter to increment bythe specified value
instead of 1. Use the format
'{counter(start,stop,step)}' where
start,stop, and step are integers. For
example, to count from 1 to 10 by 2, use
'{counter(1,11,2)}'.Note that the counter
stops counting when the stop value is
reached and does not return thestop value.
Start, stop, and step are optional and may
be omitted. For example, to countfrom 0 by
2s, use '{counter(,,2)}'.You may create an
arbitrary number of counters by appending a
unique name to the field namepreceded by a
period: '{counter.a}', '{counter.b}', etc.
Each counter will have its own stateand will
start at 0 and increment by 1 unless
otherwise specified. Note: {counter} is not
suitable for use with 'export' and '--
update' as the counter associated with a
photo may change between export sessions.
See also {id}.
{album_seq} An integer, starting at 0, indicating the
photo's index (sequence) in the containing
album. Only valid when used in a '--
filename' template and only when '{album}'
or '{folder_album}' is used in the '--
directory' template. For example '--
directory "{folder_album}" --filename
"{album_seq}_{original_name}"'. To start
counting at a value other than 0, append
append '(starting_value)' to the field name.
For example, to start counting at 1 instead
of 0: '{album_seq(1)}'. May be formatted
using a python string format code. For
example, to format as a 5-digit integer and
pad with zeros, use '{album_seq:05d}' which
results in 00000, 00001, 00002...etc. To
format while also using a starting value:
'{album_seq:05d(1)}' which results in 0001,
00002...etc.This may result in incorrect
sequences if you have duplicate albums with
the same name; see also
'{folder_album_seq}'.
{folder_album_seq} An integer, starting at 0, indicating the
photo's index (sequence) in the containing
album and folder path. Only valid when used
in a '--filename' template and only when
'{folder_album}' is used in the '--
directory' template. For example '--
directory "{folder_album}" --filename
"{folder_album_seq}_{original_name}"'. To
start counting at a value other than 0,
append '(starting_value)' to the field name.
For example, to start counting at 1 instead
of 0: '{folder_album_seq(1)}' May be
formatted using a python string format code.
For example, to format as a 5-digit integer
and pad with zeros, use
'{folder_album_seq:05d}' which results in
00000, 00001, 00002...etc. To format while
also using a starting value:
'{folder_album_seq:05d(1)}' which results in
0001, 00002...etc.This may result in
incorrect sequences if you have duplicate
albums with the same name in the same
folder; see also '{album_seq}'.
{comma} A comma: ','
{semicolon} A semicolon: ';'
{questionmark} A question mark: '?'
{pipe} A vertical pipe: '|'
{percent} A percent sign: '%'
{ampersand} an ampersand symbol: '&'
{openbrace} An open brace: '{'
{closebrace} A close brace: '}'
{openparens} An open parentheses: '('
{closeparens} A close parentheses: ')'
{openbracket} An open bracket: '['
{closebracket} A close bracket: ']'
{newline} A newline: 'n'
{lf} A line feed: 'n', alias for {newline}
{cr} A carriage return: 'r'
{crlf} A carriage return + line feed: 'rn'
{tab} :A tab: 't'
{osxphotos_version} The osxphotos version, e.g. '0.69.2'
{osxphotos_cmd_line} The full command line used to run osxphotos
The following substitutions may result in multiple values. Thus if specified
for --directory these could result in multiple copies of a photo being being
exported, one to each directory. For example: --directory
'{created.year}/{album}' could result in the same photo being exported to each
of the following directories if the photos were created in 2019 and were in
albums 'Vacation' and 'Family': 2019/Vacation, 2019/Family
Substitution Description
{album} Album(s) photo is contained in
{folder_album} Folder path + album photo is contained in. e.g.
'Folder/Subfolder/Album' or just 'Album' if no
enclosing folder
{project} Project(s) photo is contained in (such as greeting
cards, calendars, slideshows)
{album_project} Album(s) and project(s) photo is contained in;
treats projects as regular albums
{folder_album_project} Folder path + album (includes projects as albums)
photo is contained in. e.g.
'Folder/Subfolder/Album' or just 'Album' if no
enclosing folder
{keyword} Keyword(s) assigned to photo
{person} Person(s) / face(s) in a photo
{label} Image categorization label associated with a photo
(Photos 5+ only). Labels are added automatically by
Photos using machine learning algorithms to
categorize images. These are not the same as
{keyword} which refers to the user-defined
keywords/tags applied in Photos.
{label_normalized} All lower case version of 'label' (Photos 5+ only)
{comment} Comment(s) on shared Photos; format is 'Person
name: comment text' (Photos 5+ only)
{exiftool} Format: '{exiftool:GROUP:TAGNAME}'; use exiftool
(https://exiftool.org) to extract metadata, in form
GROUP:TAGNAME, from image. E.g.
'{exiftool:EXIF:Make}' to get camera make, or
{exiftool:IPTC:Keywords} to extract keywords. See
https://exiftool.org/TagNames/ for list of valid
tag names. You must specify group (e.g. EXIF,
IPTC, etc) as used in `exiftool -G`. exiftool must
be installed in the path to use this template.
{searchinfo.holiday} Holiday names associated with a photo, e.g.
'Christmas Day'; (Photos 5+ only, applied
automatically by Photos' image categorization
algorithms).
{searchinfo.activity} Activities associated with a photo, e.g. 'Sporting
Event'; (Photos 5+ only, applied automatically by
Photos' image categorization algorithms).
{searchinfo.venue} Venues associated with a photo, e.g. name of
restaurant; (Photos 5+ only, applied automatically
by Photos' image categorization algorithms).
{searchinfo.venue_type} Venue types associated with a photo, e.g.
'Restaurant'; (Photos 5+ only, applied
automatically by Photos' image categorization
algorithms).
{photo} Provides direct access to the PhotoInfo object for
the photo. Must be used in format
'{photo.property}' where 'property' represents a
PhotoInfo property. For example: '{photo.favorite}'
is the same as '{favorite}' and
'{photo.place.name}' is the same as '{place.name}'.
'{photo}' provides access to properties that are
not available as separate template fields but it
assumes some knowledge of the underlying PhotoInfo
class. See https://rhettbull.github.io/osxphotos/
for additional documentation on the PhotoInfo
class.
{detected_text} List of text strings found in the image after
performing text detection. Using '{detected_text}'
will cause osxphotos to perform text detection on
your photos using the built-in macOS text detection
algorithms which will slow down your export. The
results for each photo will be cached in the export
database so that future exports with '--update' do
not need to reprocess each photo. You may pass a
confidence threshold value between 0.0 and 1.0
after a colon as in '{detected_text:0.5}'; The
default confidence threshold is 0.75.
'{detected_text}' works only on macOS Catalina
(10.15) or later. Note: this feature is not the
same thing as Live Text in macOS Monterey, which
osxphotos does not yet support.
{shell_quote} Use in form '{shell_quote,TEMPLATE}'; quotes the
rendered TEMPLATE value(s) for safe usage in the
shell, e.g. My file.jpeg => 'My file.jpeg'; only
adds quotes if needed.
{strip} Use in form '{strip,TEMPLATE}'; strips whitespace
from begining and end of rendered TEMPLATE
value(s).
{format} Use in form '{format:TYPE:FORMAT,TEMPLATE}';
converts TEMPLATE value to TYPE then formats the
value using Python string formatting codes
specified by FORMAT; TYPE is one of: 'int',
'float', or 'str'. For example,
'{format:float:.1f,{exiftool:EXIF:FocalLength}}'
will format focal length to 1 decimal place (e.g.
'100.0').
{function} Execute a python function from an external file and
use return value as template substitution. Use in
format: {function:file.py::function_name} where
'file.py' is the path/name of the python file and
'function_name' is the name of the function to
call. The file name may also be url to a python
file, e.g. '{function:https://raw.githubusercontent
.com/RhetTbull/osxphotos/main/examples/template_fun
ction.py::example}'. The function will be passed
the PhotoInfo object for the photo. See https://git
hub.com/RhetTbull/osxphotos/blob/master/examples/te
mplate_function.py for an example of how to
implement a template function.
The following substitutions are file or directory paths. You can access
various parts of the path using the following modifiers:
{path.parent}: the parent directory
{path.name}: the name of the file or final sub-directory
{path.stem}: the name of the file without the extension
{path.suffix}: the suffix of the file including the leading '.'
For example, if the field {export_dir} is '/Shared/Backup/Photos':
{export_dir.parent} is '/Shared/Backup'
If the field {filepath} is '/Shared/Backup/Photos/IMG_1234.JPG':
{filepath.parent} is '/Shared/Backup/Photos'
{filepath.name} is 'IMG_1234.JPG'
{filepath.stem} is 'IMG_1234'
{filepath.suffix} is '.JPG'
Substitution Description
{export_dir} The full path to the export directory
{filepath} The full path to the exported file
Post Command
You can run commands on the exported photos for post-processing using the '--
post-command' option. '--post-command' is passed a CATEGORY and a COMMAND.
COMMAND is an osxphotos template string which will be rendered and passed to
the shell for execution. CATEGORY is the category of file to pass to COMMAND.
The following categories are available:
Category Description
exported All exported files
new When used with '--update', all newly exported
files
updated When used with '--update', all files which were
previously exported but updated this time
skipped When used with '--update', all files which were
skipped (because they were previously exported and
didn't change)
missing All files which were not exported because they
were missing from the Photos library
exif_updated When used with '--exiftool', all files on which
exiftool updated the metadata
touched When used with '--touch-file', all files where the
date was touched
converted_to_jpeg When used with '--convert-to-jpeg', all files
which were converted to jpeg
sidecar_json_written When used with '--sidecar json', all JSON sidecar
files which were written
sidecar_json_skipped When used with '--sidecar json' and '--update',
all JSON sidecar files which were skipped
sidecar_exiftool_written When used with '--sidecar exiftool', all exiftool
sidecar files which were written
sidecar_exiftool_skipped When used with '--sidecar exiftool' and '--update,
all exiftool sidecar files which were skipped
sidecar_xmp_written When used with '--sidecar xmp', all XMP sidecar
files which were written
sidecar_xmp_skipped When used with '--sidecar xmp' and '--update', all
XMP sidecar files which were skipped
error All files which produced an error during export
In addition to all normal template fields, the template fields '{filepath}'
and '{export_dir}' will be available to your command template. Both of these
are path-type templates which means their various parts can be accessed using
the available properties, e.g. '{filepath.name}' provides just the file name
without path and '{filepath.suffix}' is the file extension (suffix) of the
file. When using paths in your command template, it is important to properly
quote the paths as they will be passed to the shell and path names may contain
spaces. Both the '{shell_quote}' template and the '|shell_quote' template
filter are available for this purpose. For example, the following command
outputs the full path of newly exported files to file 'new.txt':
--post-command new "echo {filepath|shell_quote} >> {shell_quote,{export_dir}/exported.txt}"
In the above command, the 'shell_quote' filter is used to ensure '{filepath}'
is properly quoted and the '{shell_quote}' template ensures the constructed
path of '{exported_dir}/exported.txt' is properly quoted. If '{filepath}' is
'IMG 1234.jpeg' and '{export_dir}' is '/Volumes/Photo Export', the command
thus renders to:
echo 'IMG 1234.jpeg' >> '/Volumes/Photo Export/exported.txt'
It is highly recommended that you run osxphotos with '--dry-run --verbose'
first to ensure your commands are as expected. This will not actually run the
commands but will print out the exact command string which would be executed.
Post Function
You can run your own python functions on the exported photos for post-
processing using the '--post-function' option. '--post-function' is passed the
name a python file and the name of the function in the file to call using
format 'filename.py::function_name'. See the example function at
https://github.com/RhetTbull/osxphotos/blob/master/examples/post_function.py
You may specify multiple functions to run by repeating the --post-function
option. All post functions will be called immediately after export of each
photo and immediately before any --post-command commands. Post functions will
not be called if the --dry-run flag is set.
The OSXPhotos command line tool creates a number of files during the course of its execution. OSXPhotos adheres to the XDG standard for file locations.
$XDG_CONFIG_HOME or $HOME/.config : osxphotos directory containing configuration files, for example color themes for colorized output.$XDG_DATA_HOME or $HOME/.local/share : osxphotos directory containing local data files, for example, the help files displayed with osxphotos docs .osxphotos_crash.log file containing the stack trace of the last crash if OSXPhotos encounters a fatal error during execution.osxphotos export command): .osxphotos_export.db SQLite database containing information needed to update an export and track metadata changes in exported photos. Note : This file may contain sensitive information such as locations and the names of persons in photos so if you are using osxphotos export to share with others, you may want to delete this file. You can also specify an alternate location for the export database using the --exportdb flag during export. See also osxphotos help exportdb for more information about built in utilities for working with the export database..osxphotos_keep to load a list of file/directory patterns which should be excluded from --cleanup during export. This file uses the same rule format as .gitignore. See osxphotos help export cleanup for more information. In addition to the command line interface, OSXPhotos provides a python API you can use within your own code. For additional information on the API, see API_README.md and the osxphotos documentation.
The templating system converts one or template statements, written in osxphotos metadata templating language, to one or more rendered values using information from the photo being processed.
In its simplest form, a template statement has the form: "{template_field}" , for example "{title}" which would resolve to the title of the photo.
Template statements may contain one or more modifiers. The full syntax is:
"pretext{delim+template_field:subfield(field_arg)|filter[find,replace] conditional&combine_value?bool_value,default}posttext"
Template statements are white-space sensitive meaning that white space (spaces, tabs) changes the meaning of the template statement.
pretext and posttext are free form text. For example, if a photo has title "My Photo Title" the template statement "The title of the photo is {title}" , resolves to "The title of the photo is My Photo Title" . The pretext in this example is "The title if the photo is " and the template_field is {title} .
delim : optional delimiter string to use when expanding multi-valued template values in-place
+ : If present before template name , expands the template in place. If delim not provided, values are joined with no delimiter.
eg if Photo keywords are ["foo","bar"] :
"{keyword}" renders to "foo", "bar""{,+keyword}" renders to: "foo,bar""{; +keyword}" renders to: "foo; bar""{+keyword}" renders to "foobar" template_field : The template field to resolve. See Template Substitutions for full list of template fields.
:subfield : Some templates have sub-fields, For example, {exiftool:IPTC:Make} ; the template_field is exiftool and the sub-field is IPTC:Make .
(field_arg) : optional arguments to pass to the field; for example, with {folder_album} this is used to pass the path separator used for joining folders and albums when rendering the field (default is "/" for {folder_album} ).
|filter : You may optionally append one or more filter commands to the end of the template field using the vertical pipe ('|') symbol. Filters may be combined, separated by '|' as in: {keyword|capitalize|parens} .
Valid filters are:
lower : Convert value to lower case, eg 'Value' => 'value'.upper : Convert value to upper case, eg 'Value' => 'VALUE'.strip : Strip whitespace from beginning/end of value, eg ' Value ' => 'Value'.titlecase : Convert value to title case, eg 'my value' => 'My Value'.capitalize : Capitalize first word of value and convert other words to lower case, eg 'MY VALUE' => 'My value'.braces : Enclose value in curly braces, eg 'value => '{value}'.parens : Enclose value in parentheses, eg 'value' => '(value')brackets : Enclose value in brackets, eg 'value' => '[value]'shell_quote : Quotes the value for safe usage in the shell, eg My file.jpeg => 'My file.jpeg'; only adds quotes if needed.function : Run custom python function to filter value; use in format 'function:/path/to/file.py::function_name'. See example at https://github.com/RhetTbull/osxphotos/blob/master/examples/template_filter.pysplit(x) : Split value into a list of values using x as delimiter, eg 'value1;value2' => ['value1', 'value2'] if used with split(;).autosplit : Automatically split delimited string into separate values; will split strings delimited by comma, semicolon, or space, eg 'value1,value2' => ['value1', 'value2'].chop(x) : Remove x characters off the end of value, eg chop(1): 'Value' => 'Valu'; when applied to a list, chops characters from each list value, eg chop(1): ['travel', 'beach']=> ['trave', 'beac'].chomp(x) : Remove x characters from the beginning of value, eg chomp(1): ['Value'] => ['alue']; when applied to a list, removes characters from each list value, eg chomp(1): ['travel', 'beach']=> ['ravel', 'each'].sort : Sort list of values, eg ['c', 'b', 'a'] => ['a', 'b', 'c'].rsort : Sort list of values in reverse order, eg ['a', 'b', 'c'] => ['c', 'b', 'a'].reverse : Reverse order of values, eg ['a', 'b', 'c'] => ['c', 'b', 'a'].uniq : Remove duplicate values, eg ['a', 'b', 'c', 'b', 'a'] => ['a', 'b', 'c'].join(x) : Join list of values with delimiter x, eg join(,): ['a', 'b', 'c'] => 'a,b,c'; the DELIM option functions similar to join(x) but with DELIM, the join happens before being passed to any filters.May optionally be used without an argument, that is 'join()' which joins values together with no delimiter. eg join(): ['a', 'b', 'c'] => 'abc'.append(x) : Append x to list of values, eg append(d): ['a', 'b', 'c'] => ['a', 'b', 'c', 'd'].prepend(x) : Prepend x to list of values, eg prepend(d): ['a', 'b', 'c'] => ['d', 'a', 'b', 'c'].appends(x) : Append s[tring] Append x to each value of list of values, eg appends(d): ['a', 'b', 'c'] => ['ad', 'bd', 'cd'].prepends(x) : Prepend s[tring] x to each value of list of values, eg prepends(d): ['a', 'b', 'c'] => ['da', 'db', 'dc'].remove(x) : Remove x from list of values, eg remove(b): ['a', 'b', 'c'] => ['a', 'c'].slice(start:stop:step) : Slice list using same semantics as Python's list slicing, eg slice(1:3): ['a', 'b', 'c', 'd'] => ['b', 'c']; slice(1:4:2): ['a', 'b', 'c', 'd'] => ['b', 'd']; slice(1:): ['a', 'b', 'c', 'd'] => ['b', 'c', 'd']; slice(:-1): ['a', 'b', 'c', 'd'] => ['a', 'b', 'c']; slice(::-1): ['a', 'b', 'c', 'd'] => ['d', 'c', 'b', 'a']. See also sslice().sslice(start:stop:step) : [s(tring) slice] Slice values in a list using same semantics as Python's string slicing, eg sslice(1:3):'abcd => 'bc'; sslice(1:4:2): 'abcd' => 'bd', etc. See also slice().filter(x) : Filter list of values using predicate x; for example, {folder_album|filter(contains Events)} returns only folders/albums containing the word 'Events' in their path.int : Convert values in list to integer, eg 1.0 => 1. If value cannot be converted to integer, remove value from list. ['1.1', 'x'] => ['1']. See also float.float : Convert values in list to floating point number, eg 1 => 1.0. If value cannot be converted to float, remove value from list. ['1', 'x'] => ['1.0']. See also int. eg if Photo keywords are ["FOO","bar"] :
"{keyword|lower}" renders to "foo", "bar""{keyword|upper}" renders to: "FOO", "BAR""{keyword|capitalize}" renders to: "Foo", "Bar""{keyword|lower|parens}" renders to: "(foo)", "(bar)"eg if Photo description is "my description":
"{descr|titlecase}" renders to: "My Description" eg If Photo is in Album1 in Folder1 :
"{folder_album}" renders to ["Folder1/Album1"]"{folder_album(>)}" renders to ["Folder1>Album1"]"{folder_album()}" renders to ["Folder1Album1"] [find,replace] : optional text replacement to perform on rendered template value. For example, to replace "/" in an album name, you could use the template "{album[/,-]}" . Multiple replacements can be made by appending "|" and adding another find|replace pair. eg to replace both "/" and ":" in album name: "{album[/,-|:,-]}" . find/replace pairs are not limited to single characters. The "|" character cannot be used in a find/replace pair.
conditional : optional conditional expression that is evaluated as boolean (True/False) for use with the ?bool_value modifier. Conditional expressions take the form ' not operator value ' where not is an optional modifier that negates the operator . Note: the space before the conditional expression is required if you use a conditional expression. Valid comparison operators are:
contains : template field contains value, similar to python's inmatches : template field contains exactly value, unlike contains : does not match partial matchesstartswith : template field starts with valueendswith : template field ends with value<= : template field is less than or equal to value>= : template field is greater than or equal to value< : template field is less than value> : template field is greater than value== : template field equals value!= : template field does not equal value The value part of the conditional expression is treated as a bare (unquoted) word/phrase. Multiple values may be separated by '|' (the pipe symbol). value is itself a template statement so you can use one or more template fields in value which will be resolved before the comparison occurs.
على سبيل المثال:
{keyword matches Beach} resolves to True if 'Beach' is a keyword. It would not match keyword 'BeachDay'.{keyword contains Beach} resolves to True if any keyword contains the word 'Beach' so it would match both 'Beach' and 'BeachDay'.{photo.score.overall > 0.7} resolves to True if the photo's overall aesthetic score is greater than 0.7.{keyword|lower contains beach} uses the lower case filter to do case-insensitive matching to match any keyword that contains the word 'beach'.{keyword|lower not contains beach} uses the not modifier to negate the comparison so this resolves to True if there is no keyword that matches 'beach'. Examples: to export photos that contain certain keywords with the osxphotos export command's --directory option:
--directory "{keyword|lower matches travel|vacation?Travel-Photos,Not-Travel-Photos}"
This exports any photo that has keywords 'travel' or 'vacation' into a directory 'Travel-Photos' and all other photos into directory 'Not-Travel-Photos'.
This can be used to rename files as well, for example: --filename "{favorite?Favorite-{original_name},{original_name}}"
This renames any photo that is a favorite as 'Favorite-ImageName.jpg' (where 'ImageName.jpg' is the original name of the photo) and all other photos with the unmodified original name.
&combine_value : Template fields may be combined with another template statement to return multiple values. The combine_value is another template statement. For example, the template {created.year&{folder_album,}} would resolve to ["1999", "Vacation"] if the photo was created in 1999 and was in the album Vacation. Because the combine_value is a template statement, multiple templates may be combined together by nesting the combine operator: {template1&{template2&{template3,},},}. In this example, a null default value is used to prevent the default value from being combined if any of the nested templates does not resolve to a value
?bool_value : Template fields may be evaluated as boolean (True/False) by appending "?" after the field name (and following "(field_arg)" or "[find/replace]". If a field is True (eg photo is HDR and field is "{hdr}" ) or has any value, the value following the "?" will be used to render the template instead of the actual field value. If the template field evaluates to False (eg in above example, photo is not HDR) or has no value (eg photo has no title and field is "{title}" ) then the default value following a "," will be used.
eg if photo is an HDR image,
"{hdr?ISHDR,NOTHDR}" renders to "ISHDR"and if it is not an HDR image,
"{hdr?ISHDR,NOTHDR}" renders to "NOTHDR" ,default : optional default value to use if the template name has no value. This modifier is also used for the value if False for boolean-type fields (see above) as well as to hold a sub-template for values like {created.strftime} . If no default value provided, "_" is used.
eg, if photo has no title set,
"{title}" renders to "_""{title,I have no title}" renders to "I have no title" Template fields such as created.strftime use the default value to pass the template to use for strftime .
eg, if photo date is 4 February 2020, 19:07:38,
"{created.strftime,%Y-%m-%d-%H%M%S}" renders to "2020-02-04-190738" Some template fields such as "{media_type}" use the default value to allow customization of the output. For example, "{media_type}" resolves to the special media type of the photo such as panorama or selfie . You may use the default value to override these in form: "{media_type,video=vidéo;time_lapse=vidéo_accélérée}" . In this example, if photo was a time_lapse photo, media_type would resolve to vidéo_accélérée instead of time_lapse .
Either or both bool_value or default (False value) may be empty which would result in empty string "" when rendered.
If you want to include "{" or "}" in the output, use "{openbrace}" or "{closebrace}" template substitution.
eg "{created.year}/{openbrace}{title}{closebrace}" would result in "2020/{Photo Title}" .
المتغيرات
You can define variables for later use in the template string using the format {var:NAME,VALUE} where VALUE is a template statement. Variables may then be referenced using the format %NAME . For example: {var:foo,bar} defines the variable %foo to have value bar . This can be useful if you want to re-use a complex template value in multiple places within your template string or for allowing the use of characters that would otherwise be prohibited in a template string. For example, the "pipe" ( | ) character is not allowed in a find/replace pair but you can get around this limitation like so: {var:pipe,{pipe}}{title[-,%pipe]} which replaces the - character with | (the value of %pipe ).
Another use case for variables is filtering combined template values. For example, using the &combine_value mechanism to combine two template values that might result in duplicate values, you could do the following: {var:myvar,{template1&{template2,},}}{%myvar|uniq} which allows the use of the uniq filter against the combined template values.
Variables can also be referenced as fields in the template string, for example: {var:year,{created.year}}{original_name}-{%year} . In some cases, use of variables can make your template string more readable. Variables can be used as template fields, as values for filters, as values for conditional operations, or as default values. When used as a conditional value or default value, variables should be treated like any other field and enclosed in braces as conditional and default values are evaluated as template strings. For example: {var:name,Katie}{person contains {%name}?{%name},Not-{%name}} .
If you need to use a % (percent sign character), you can escape the percent sign by using %% . You can also use the {percent} template field where a template field is required. على سبيل المثال:
{title[:,%%]} replaces the : with % and {title contains Foo?{title}{percent},{title}} adds % to the title if it contains Foo .
The following template field substitutions are availabe for use the templating system.
| مجال | وصف |
|---|---|
| {اسم} | Current filename of the photo |
| {original_name} | Photo's original filename when imported to Photos |
| {عنوان} | Title of the photo |
| {descr} | Description of the photo |
| {media_type} | Special media type resolved in this precedence: selfie, time_lapse, panorama, slow_mo, screenshot, screen_recording, portrait, live_photo, burst, photo, video. Defaults to 'photo' or 'video' if no special type. Customize one or more media types using format: '{media_type,video=vidéo;time_lapse=vidéo_accélérée}' |
| {photo_or_video} | 'photo' or 'video' depending on what type the image is. To customize, use default value as in '{photo_or_video,photo=fotos;video=videos}' |
| {hdr} | Photo is HDR?; True/False value, use in format '{hdr?VALUE_IF_TRUE,VALUE_IF_FALSE}' |
| {edited} | True if photo has been edited (has adjustments), otherwise False; use in format '{edited?VALUE_IF_TRUE,VALUE_IF_FALSE}' |
| {edited_version} | True if template is being rendered for the edited version of a photo, otherwise False. |
| {مفضل} | Photo has been marked as favorite?; True/False value, use in format '{favorite?VALUE_IF_TRUE,VALUE_IF_FALSE}' |
| {مخلوق} | Photo's creation date in ISO format, eg '2020-03-22' |
| {created.date} | Photo's creation date in ISO format, eg '2020-03-22' |
| {created.year} | 4-digit year of photo creation time |
| {created.yy} | 2-digit year of photo creation time |
| {created.mm} | 2-digit month of the photo creation time (zero padded) |
| {created.month} | Month name in user's locale of the photo creation time |
| {created.mon} | Month abbreviation in the user's locale of the photo creation time |
| {created.dd} | 2-digit day of the month (zero padded) of photo creation time |
| {created.dow} | Day of week in user's locale of the photo creation time |
| {created.doy} | 3-digit day of year (eg Julian day) of photo creation time, starting from 1 (zero padded) |
| {created.hour} | 2-digit hour of the photo creation time |
| {created.min} | 2-digit minute of the photo creation time |
| {created.sec} | 2-digit second of the photo creation time |
| {created.strftime} | Apply strftime template to file creation date/time. Should be used in form {created.strftime,TEMPLATE} where TEMPLATE is a valid strftime template, eg {created.strftime,%Y-%U} would result in year-week number of year: '2020-23'. If used with no template will return null value. See https://strftime.org/ for help on strftime templates. |
| {معدل} | Photo's modification date in ISO format, eg '2020-03-22'; uses creation date if photo is not modified |
| {modified.date} | Photo's modification date in ISO format, eg '2020-03-22'; uses creation date if photo is not modified |
| {modified.year} | 4-digit year of photo modification time; uses creation date if photo is not modified |
| {modified.yy} | 2-digit year of photo modification time; uses creation date if photo is not modified |
| {modified.mm} | 2-digit month of the photo modification time (zero padded); uses creation date if photo is not modified |
| {modified.month} | Month name in user's locale of the photo modification time; uses creation date if photo is not modified |
| {modified.mon} | Month abbreviation in the user's locale of the photo modification time; uses creation date if photo is not modified |
| {modified.dd} | 2-digit day of the month (zero padded) of the photo modification time; uses creation date if photo is not modified |
| {modified.dow} | Day of week in user's locale of the photo modification time; uses creation date if photo is not modified |
| {modified.doy} | 3-digit day of year (eg Julian day) of photo modification time, starting from 1 (zero padded); uses creation date if photo is not modified |
| {modified.hour} | 2-digit hour of the photo modification time; uses creation date if photo is not modified |
| {modified.min} | 2-digit minute of the photo modification time; uses creation date if photo is not modified |
| {modified.sec} | 2-digit second of the photo modification time; uses creation date if photo is not modified |
| {modified.strftime} | Apply strftime template to file modification date/time. Should be used in form {modified.strftime,TEMPLATE} where TEMPLATE is a valid strftime template, eg {modified.strftime,%Y-%U} would result in year-week number of year: '2020-23'. If used with no template will return null value. Uses creation date if photo is not modified. See https://strftime.org/ for help on strftime templates. |
| {اليوم} | Current date in iso format, eg '2020-03-22' |
| {today.date} | Current date in iso format, eg '2020-03-22' |
| {today.year} | 4-digit year of current date |
| {today.yy} | 2-digit year of current date |
| {today.mm} | 2-digit month of the current date (zero padded) |
| {today.month} | Month name in user's locale of the current date |
| {today.mon} | Month abbreviation in the user's locale of the current date |
| {today.dd} | 2-digit day of the month (zero padded) of current date |
| {today.dow} | Day of week in user's locale of the current date |
| {today.doy} | 3-digit day of year (eg Julian day) of current date, starting from 1 (zero padded) |
| {today.hour} | 2-digit hour of the current date |
| {today.min} | 2-digit minute of the current date |
| {today.sec} | 2-digit second of the current date |
| {today.strftime} | Apply strftime template to current date/time. Should be used in form {today.strftime,TEMPLATE} where TEMPLATE is a valid strftime template, eg {today.strftime,%Y-%U} would result in year-week number of year: '2020-23'. If used with no template will return null value. See https://strftime.org/ for help on strftime templates. |
| {place.name} | Place name from the photo's reverse geolocation data, as displayed in Photos |
| {place.country_code} | The ISO country code from the photo's reverse geolocation data |
| {place.name.country} | Country name from the photo's reverse geolocation data |
| {place.name.state_province} | State or province name from the photo's reverse geolocation data |
| {place.name.city} | City or locality name from the photo's reverse geolocation data |
| {place.name.area_of_interest} | Area of interest name (eg landmark or public place) from the photo's reverse geolocation data |
| {place.address} | Postal address from the photo's reverse geolocation data, eg '2007 18th St NW, Washington, DC 20009, United States' |
| {place.address.street} | Street part of the postal address, eg '2007 18th St NW' |
| {place.address.city} | City part of the postal address, eg 'Washington' |
| {place.address.state_province} | State/province part of the postal address, eg 'DC' |
| {place.address.postal_code} | Postal code part of the postal address, eg '20009' |
| {place.address.country} | Country name of the postal address, eg 'United States' |
| {place.address.country_code} | ISO country code of the postal address, eg 'US' |
| {searchinfo.season} | Season of the year associated with a photo, eg 'Summer'; (Photos 5+ only, applied automatically by Photos' image categorization algorithms). |
| {exif.camera_make} | Camera make from original photo's EXIF information as imported by Photos, eg 'Apple' |
| {exif.camera_model} | Camera model from original photo's EXIF information as imported by Photos, eg 'iPhone 6s' |
| {exif.lens_model} | Lens model from original photo's EXIF information as imported by Photos, eg 'iPhone 6s back camera 4.15mm f/2.2' |
| {لحظة} | The moment title of the photo |
| {uuid} | Photo's internal universally unique identifier (UUID) for the photo, a 36-character string unique to the photo, eg '128FB4C6-0B16-4E7D-9108-FB2E90DA1546' |
| {shortuuid} | A shorter representation of photo's internal universally unique identifier (UUID) for the photo, a 22-character string unique to the photo, eg 'JYsxugP9UjetmCbBCHXcmu' |
| {بطاقة تعريف} | A unique number for the photo based on its primary key in the Photos database. A sequential integer, eg 1, 2, 3...etc. Each asset associated with a photo (eg an image and Live Photo preview) will share the same id. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{id:05d}' which results in 00001, 00002, 00003...etc. |
| {عداد} | A sequential counter, starting at 0, that increments each time it is evaluated.To start counting at a value other than 0, append append '(starting_value)' to the field name.For example, to start counting at 1 instead of 0: '{counter(1)}'.May be formatted using a python string format code.For example, to format as a 5-digit integer and pad with zeros, use '{counter:05d(1)}'which results in 00001, 00002, 00003...etc.You may also specify a stop value which causes the counter to reset to the starting valuewhen the stop value is reached and a step size which causes the counter to increment bythe specified value instead of 1. Use the format '{counter(start,stop,step)}' where start,stop, and step are integers. For example, to count from 1 to 10 by 2, use '{counter(1,11,2)}'.Note that the counter stops counting when the stop value is reached and does not return thestop value. Start, stop, and step are optional and may be omitted. For example, to countfrom 0 by 2s, use '{counter(,,2)}'.You may create an arbitrary number of counters by appending a unique name to the field namepreceded by a period: '{counter.a}', '{counter.b}', etc. Each counter will have its own stateand will start at 0 and increment by 1 unless otherwise specified. Note: {counter} is not suitable for use with 'export' and '--update' as the counter associated with a photo may change between export sessions. See also {id}. |
| {album_seq} | An integer, starting at 0, indicating the photo's index (sequence) in the containing album. Only valid when used in a '--filename' template and only when '{album}' or '{folder_album}' is used in the '--directory' template. For example '--directory "{folder_album}" --filename "{album_seq}_{original_name}"'. To start counting at a value other than 0, append append '(starting_value)' to the field name. For example, to start counting at 1 instead of 0: '{album_seq(1)}'. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{album_seq:05d}' which results in 00000, 00001, 00002...etc. To format while also using a starting value: '{album_seq:05d(1)}' which results in 0001, 00002...etc.This may result in incorrect sequences if you have duplicate albums with the same name; see also '{folder_album_seq}'. |
| {folder_album_seq} | An integer, starting at 0, indicating the photo's index (sequence) in the containing album and folder path. Only valid when used in a '--filename' template and only when '{folder_album}' is used in the '--directory' template. For example '--directory "{folder_album}" --filename "{folder_album_seq}_{original_name}"'. To start counting at a value other than 0, append '(starting_value)' to the field name. For example, to start counting at 1 instead of 0: '{folder_album_seq(1)}' May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{folder_album_seq:05d}' which results in 00000, 00001, 00002...etc. To format while also using a starting value: '{folder_album_seq:05d(1)}' which results in 0001, 00002...etc.This may result in incorrect sequences if you have duplicate albums with the same name in the same folder; see also '{album_seq}'. |
| {فاصلة} | A comma: ',' |
| {semicolon} | A semicolon: ';' |
| {questionmark} | A question mark: '?' |
| {ماسورة} | A vertical pipe: '|' |
| {percent} | A percent sign: '%' |
| {ampersand} | an ampersand symbol: '&' |
| {openbrace} | An open brace: '{' |
| {closebrace} | A close brace: '}' |
| {openparens} | An open parentheses: '(' |
| {closeparens} | A close parentheses: ')' |
| {openbracket} | An open bracket: '[' |
| {closebracket} | A close bracket: ']' |
| {newline} | A newline: 'n' |
| {lf} | A line feed: 'n', alias for {newline} |
| {cr} | A carriage return: 'r' |
| {crlf} | A carriage return + line feed: 'rn' |
| {فاتورة غير مدفوعة} | :A tab: 't' |
| {osxphotos_version} | The osxphotos version, eg '0.69.2' |
| {osxphotos_cmd_line} | The full command line used to run osxphotos |
| {album} | Album(s) photo is contained in |
| {folder_album} | Folder path + album photo is contained in. eg 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder |
| {مشروع} | Project(s) photo is contained in (such as greeting cards, calendars, slideshows) |
| {album_project} | Album(s) and project(s) photo is contained in; treats projects as regular albums |
| {folder_album_project} | Folder path + album (includes projects as albums) photo is contained in. eg 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder |
| {keyword} | Keyword(s) assigned to photo |
| {شخص} | Person(s) / face(s) in a photo |
| {ملصق} | Image categorization label associated with a photo (Photos 5+ only). Labels are added automatically by Photos using machine learning algorithms to categorize images. These are not the same as {keyword} which refers to the user-defined keywords/tags applied in Photos. |
| {label_normalized} | All lower case version of 'label' (Photos 5+ only) |
| {تعليق} | Comment(s) on shared Photos; format is 'Person name: comment text' (Photos 5+ only) |
| {exiftool} | Format: '{exiftool:GROUP:TAGNAME}'; use exiftool (https://exiftool.org) to extract metadata, in form GROUP:TAGNAME, from image. Eg '{exiftool:EXIF:Make}' to get camera make, or {exiftool:IPTC:Keywords} to extract keywords. See https://exiftool.org/TagNames/ for list of valid tag names. You must specify group (eg EXIF, IPTC, etc) as used in exiftool -G . exiftool must be installed in the path to use this template. |
| {searchinfo.holiday} | Holiday names associated with a photo, eg 'Christmas Day'; (Photos 5+ only, applied automatically by Photos' image categorization algorithms). |
| {searchinfo.activity} | Activities associated with a photo, eg 'Sporting Event'; (Photos 5+ only, applied automatically by Photos' image categorization algorithms). |
| {searchinfo.venue} | Venues associated with a photo, eg name of restaurant; (Photos 5+ only, applied automatically by Photos' image categorization algorithms). |
| {searchinfo.venue_type} | Venue types associated with a photo, eg 'Restaurant'; (Photos 5+ only, applied automatically by Photos' image categorization algorithms). |
| {صورة} | Provides direct access to the PhotoInfo object for the photo. Must be used in format '{photo.property}' where 'property' represents a PhotoInfo property. For example: '{photo.favorite}' is the same as '{favorite}' and '{photo.place.name}' is the same as '{place.name}'. '{photo}' provides access to properties that are not available as separate template fields but it assumes some knowledge of the underlying PhotoInfo class. See https://rhettbull.github.io/osxphotos/ for additional documentation on the PhotoInfo class. |
| {detected_text} | List of text strings found in the image after performing text detection. Using '{detected_text}' will cause osxphotos to perform text detection on your photos using the built-in macOS text detection algorithms which will slow down your export. The results for each photo will be cached in the export database so that future exports with '--update' do not need to reprocess each photo. You may pass a confidence threshold value between 0.0 and 1.0 after a colon as in '{detected_text:0.5}'; The default confidence threshold is 0.75. '{detected_text}' works only on macOS Catalina (10.15) or later. Note: this feature is not the same thing as Live Text in macOS Monterey, which osxphotos does not yet support. |
| {shell_quote} | Use in form '{shell_quote,TEMPLATE}'; quotes the rendered TEMPLATE value(s) for safe usage in the shell, eg My file.jpeg => 'My file.jpeg'; only adds quotes if needed. |
| {يجرد} | Use in form '{strip,TEMPLATE}'; strips whitespace from begining and end of rendered TEMPLATE value(s). |
| {شكل} | Use in form '{format:TYPE:FORMAT,TEMPLATE}'; converts TEMPLATE value to TYPE then formats the value using Python string formatting codes specified by FORMAT; TYPE is one of: 'int', 'float', or 'str'. For example, '{format:float:.1f,{exiftool:EXIF:FocalLength}}' will format focal length to 1 decimal place (eg '100.0'). |
| {وظيفة} | Execute a python function from an external file and use return value as template substitution. Use in format: {function:file.py::function_name} where 'file.py' is the path/name of the python file and 'function_name' is the name of the function to call. The file name may also be url to a python file, eg '{function:https://raw.githubusercontent.com/RhetTbull/osxphotos/main/examples/template_function.py::example}'. The function will be passed the PhotoInfo object for the photo. See https://github.com/RhetTbull/osxphotos/blob/master/examples/template_function.py for an example of how to implement a template function. |
Contributing is easy! if you find bugs or want to suggest additional features/changes, please open an issue or join the discussion.
I'll gladly consider pull requests for bug fixes or feature implementations.
If you have an interesting example that shows usage of this package, submit an issue or pull request and i'll include it or link to it.
Testing against "real world" Photos libraries would be especially helpful. If you discover issues in testing against your Photos libraries, please open an issue. I've done extensive testing against my own Photos library but that's a single data point and I'm certain there are issues lurking in various edge cases I haven't discovered yet.
شكراً لهؤلاء الأشخاص الرائعين (مفتاح الرموز التعبيرية):
britiscurious | Michel Wortmann | Pablo 'merKur' Kohan | hshore29 | Daniel M. Drucker ؟ ؟ ؟ | Jean-Yves Stervinou | Thibault Deutsch |
grundsch | Ag Primatic | Horst Höck | Jonathan Strine | finestream ؟ ؟ | Aravindo Wingeier | Kristoffer Dalby |
Rott-Apple ؟ | narensankar0529 ؟ ؟ | مارتن ؟ ؟ | davidjroos | Neil Pankey ؟ | Aaron van Geffen | ubrandes ؟ |
Philippe Dewost ؟ | kaduskj ؟ | mkirkland4874 ؟ | Joseph Commisso ؟ | David Singer ؟ | oPromessa ؟ ؟ | Spencer Chang ؟ |
David Gleich | Alan de Freitas ؟ | Andrew Louis | neebah ؟ | Ahti Liin ؟ | Xiaoliang Wu | nullpointerninja ؟ ؟ |
كيم ؟ | Christoph ؟ | franzone ؟ | John Muccigrosso ؟ | Thomas K. Running ؟ | Davlatjon Shavkatov | zephyr325 ؟ |
drodner ؟ ؟ | Ferdia McKeogh ؟ | Michael Petrochuk ؟ | Quin Eddy ؟ ؟ | John Sturgeon ؟ | mave2k | Daniel Beadle ؟ |
Dave Bullock ؟ ؟ ؟ | Pweaver ؟ ؟ | aa599 ؟ ؟ | Steve Duncan ؟ | Ian Moir ؟ | Peking Duck ؟ ؟ | Christian Clauss |
dvdkon | wernerzj ؟ | rajscode ؟ | MaxLyt ؟ | ces3001 ؟ | msolo ؟ | Trygve Vea ؟ |
hydrrrrr ؟ | خافيير ؟ | Kirill A. Korinsky | Nils Breunese ؟ | 420gofOGKush ؟ | Tjalve Aarflot ؟ | mikapietrus ؟ |
santiagoGPNC ؟ | nkxco ؟ | nicad | Mike Kenyon ؟ ؟ | LunarLanding ؟ | mlevin77 ؟ | Axel Karjalainen |
Eric Mika ؟ | odedia ؟ ؟ ؟ | Tor Arne Vestbø ؟ ؟ | Frederic Garzon ؟ | Ramon Felciano ؟ ؟ | Dion Weston | Andy Blyler |
lasjoe ؟ | Daniel Vogelnest ؟ ؟ | alban73 ؟ ؟ | justaLoli ؟ | arthurward ؟ | svet-b ؟ | Syntaxheld ؟ |
Christian Sievers | Avery Chan ؟ | dobernhardt ؟ |
This project follows the all-contributors specification. Contributions of any kind welcome!
My goal is make osxphotos as reliable and comprehensive as possible. The test suite currently has over 800 tests--but there are still some bugs or incomplete features lurking. If you find bugs please open an issue. Please consult the list of open bugs before deciding that you want to use this code on your Photos library. Notable issues include:
--download-missing option for osxphotos export does not work correctly with burst images. It will download the primary image but not the other burst images. See Issue #75. This package works by creating a copy of the sqlite3 database that photos uses to store data about the photos library. The class PhotosDB then queries this database to extract information about the photos such as persons (faces identified in the photos), albums, keywords, etc. If your library is large, the database can be hundreds of MB in size and the copy read then can take many 10s of seconds to complete. Once copied, the entire database is processed and an in-memory data structure is created meaning all subsequent accesses of the PhotosDB object occur much more quickly. The database processing code is rather ugly (though it works and is well tested). Were I to start this project today, I'd likely use something like SQLAlchemy to map Python objects to the underlying SQL database instead of the way osxphotos does things today.
If apple changes the database format this will likely break.
For additional details about how osxphotos is implemented or if you would like to extend the code, see the wiki.
This project was originally inspired by photo-export by Patrick Fältström, Copyright (c) 2015 Patrik Fältström [email protected]
I use py-applescript by "Raymond Yee / rdhyee" to interact with Photos. Rather than import this package, I included the entire package (which is published as public domain code) in a private package to prevent ambiguity with other applescript packages on PyPi. py-applescript uses a native bridge via PyObjC and is very fast compared to the other osascript based packages.