OSXPhotos provides the ability to interact with and query Apple’s Photos.app library on macOS. You can query the Photos library database — for example, file name, file path, and metadata such as keywords/tags, persons/faces, albums, etc. You can also easily export both the original and edited photos.
- Supported operating systems
- Installation
- Command Line Usage
- Python API
- Template System
- Related Projects
- Contributing
- Known Bugs and Limitations
- Implementation Notes
- Acknowledgements
Supported operating systems
Only works on macOS (aka Mac OS X). Tested on macOS Sierra (10.12.6) through macOS Monterey (12.0.1). Tested on both x86 and Apple silicon (M1).
macOS Version | macOS name | Photos.app version |
---|---|---|
13.0 | Ventura | 8.0 ? * |
12.0 – 12.4 | Monterey | 7.0 |
10.16, 11.0-11.4 | Big Sur | 6.0 |
10.15.1 – 10.15.7 | Catalina | 5.0 |
10.14.5, 10.14.6 | Mojave | 4.0 |
10.13.6 | High Sierra | 3.0 |
10.12.6 | Sierra | 2.0 |
* Basic functionality has been tested on a Photos library created with the developer preview of macOS Ventura (13.0). I do not have access to a Mac running Ventura beta to do further testing.
** Some features may not be fully supported on Monterey. Notably, --use-photokit
and --download-missing
may or may not work depending on your configuration; this is a known issue that will be fixed if I can find a solution. Many users successfully use OSXPhotos on Monterey without problem.
This package will read Photos databases for any supported version on any supported macOS version. E.g. you can read a database created with Photos 5.0 on MacOS 10.15 on a machine running macOS 10.12 and vice versa.
Requires python >= 3.9
.
Installation
If you are new to python, I recommend you to install using pipx. See other advanced options below.
Installation using pipx
If you aren’t familiar with installing python applications, I recommend you install osxphotos
with pipx. If you use pipx
, you will not need to create a virtual environment as pipx
takes care of this. The easiest way to do this on a Mac is to use homebrew:
- Open
Terminal
(search forTerminal
in Spotlight or look inApplications/Utilities
) - Install
homebrew
according to instructions at https://brew.sh/ - Type the following into Terminal:
brew install pipx
- Then type this:
pipx install osxphotos
- Now you should be able to run
osxphotos
by typing:osxphotos
Once you’ve installed osxphotos with pipx, to upgrade to the latest version:
Installation using pip
You can also install directly from pypi:
Once you’ve installed osxphotos with pip, to upgrade to the latest version:
pip install --upgrade osxphotos
Installation from git repository
OSXPhotos uses setuptools, thus simply run:
git clone https://github.com/RhetTbull/osxphotos.git
cd osxphotos
python3 setup.py install
I recommend you create a virtual environment before installing osxphotos.
WARNING The git repo for this project is very large (> 1GB) because it contains multiple Photos libraries used for testing on different versions of macOS. If you just want to use the osxphotos package in your own code, I recommend you install the latest version from PyPI which does not include all the test libraries. If you just want to use the command line utility, you can download a pre-built executable of the latest release or you can install via pip
which also installs the command line app. If you aren’t comfortable with running python on your Mac, start with the pre-built executable or pipx
as described above.
Once you’ve installed osxphotos via the git repository, to upgrade to the latest version:
cd osxphotos
git pull
python3 setup.py install
Installing pre-built executable
You can also download a stand-alone pre-built executable–that doesn’t require installing python–from the releases page. Look for the file with a name similar to osxphotos_MacOS_exe_darwin_x64_v0.42.9.zip
. In this case v0.42.9
specifies version 0.42.9. Unzip the file and put the included osxphotos
binary in your system path. Currently, the binary is not signed or notarized so you’ll have to authorize the app to run in the System Preferences | Security & Privacy settings. It’s also likely this executable will not run on M1 Macs. If you don’t know how to do this, I recommend using pipx
as described above.
Getting Help
OSXPhotos is well documented. See the tutorial for a description of key features. The tutorial can be accessed using the command osxphotos tutorial
via the command line. If you are interested in using OSXPhotos in your own code, see API_README.md for a description of the API as well as the example programs. The full documentation is available online and can also be accessed using the command osxphotos docs
via the command line.
If you have questions, would like to show off projects created with OSXPhotos, or if you just want to say hello, please use the GitHub discussions forum or the osxphotos subreddit on Reddit.
Command Line Usage
This package will install a command line utility called osxphotos
that allows you to query the Photos database. Alternatively, you can also run the command line utility like this: python3 -m osxphotos
osxphotos help command_name
, for example, osxphotos help export
to get help on the export
command.
Some of the commands such as export
and query
have a large number of options. To search for options related to a specific topic, you can use osxphotos help command_name topic_name
. For example, osxphotos help export raw
finds the options related to RAW files (search is case-insensitive):
Usage: osxphotos export [OPTIONS] [PHOTOS_LIBRARY]... 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).
Command line examples
export all photos to ~/Desktop/export group in folders by date created
osxphotos export --export-by-date ~/Pictures/Photos Library.photoslibrary ~/Desktop/export
Note: Photos library/database path can also be specified using --db
option:
osxphotos export --export-by-date --db ~/Pictures/Photos Library.photoslibrary ~/Desktop/export
find all photos with keyword “Kids” and output results to json file named results.json
osxphotos query --keyword Kids --json ~/Pictures/Photos Library.photoslibrary >results.json
Find all videos larger than 200MB and add them to an album named “Big Videos” in Photos, creating the album if necessary
osxphotos query --only-movies --min-size 200MB --add-to-album "Big Videos"
Tutorial
The design philosophy for osxphotos is “make the easy things easy and make the hard things possible”. To “make the hard things possible”, osxphotos is very flexible and has many, many configuration options — the export
command for example, has over 100 command line options. Thus, osxphotos may seem daunting at first. The purpose of this tutorial is to explain a number of common use cases with examples and, hopefully, make osxphotos less daunting to use. osxphotos includes several commands for retrieving information from your Photos library but the one most users are interested in is the export
command which exports photos from the library so that’s the focus of this tutorial.
Export your photos
osxphotos export /path/to/export
This command exports all your photos to the /path/to/export
directory.
Note: osxphotos uses the term ‘photo’ to refer to a generic media asset in your Photos Library. A photo may be an image, a video file, a combination of still image and video file (e.g. an Apple “Live Photo” which is an image and an associated “live preview” video file), a JPEG image with an associated RAW image, etc.
Export by date
While the previous command will export all your photos (and videos–see note above), it probably doesn’t do exactly what you want. In the previous example, all the photos will be exported to a single folder: /path/to/export
. If you have a large library with thousands of images and videos, this likely isn’t very useful. You can use the --export-by-date
option to export photos to a folder structure organized by year, month, day, e.g. 2021/04/21
:
osxphotos export /path/to/export --export-by-date
With this command, a photo that was created on 31 May 2015 would be exported to: /path/to/export/2015/05/31
Specify directory structure
If you prefer a different directory structure for your exported images, osxphotos provides a very flexible Template System that allows you to specify the directory structure using the --directory
option. For example, this command exported to a directory structure that looks like: 2015/May
(4-digit year / month name):
osxphotos export /path/to/export --directory "{created.year}/{created.month}"
The string following --directory
is an osxphotos template string
. Template strings are widely used throughout osxphotos and it’s worth your time to learn more about them. In a template string, the values between the curly braces, e.g. {created.year}
are replaced with metadata from the photo being exported. In this case, {created.year}
is the 4-digit year of the photo’s creation date and {created.month}
is the full month name in the user’s locale (e.g. May
, mai
, etc.). In the osxphotos template system these are referred to as template fields. The text not included between {}
pairs is interpreted literally, in this case /
, is a directory separator.
osxphotos provides access to almost all the metadata known to Photos about your images. For example, Photos performs reverse geolocation lookup on photos that contain GPS coordinates to assign place names to the photo. Using the --directory
template, you could thus export photos organized by country name:
osxphotos export /path/to/export --directory "{created.year}/{place.name.country}"
Of course, some photos might not have an associated place name so the template system allows you specify a default value to use if a template field is null (has no value).
osxphotos export /path/to/export --directory "{created.year}/{place.name.country,No-Country}"
The value after the ‘,’ in the template string is the default value, in this case ‘No-Country’. Note: If you don’t specify a default value and a template field is null, osxphotos will use “_” (underscore character) as the default.
Some template fields, such as {keyword}
, may expand to more than one value. For example, if a photo has keywords of “Travel” and “Vacation”, {keyword}
would expand to “Travel”, “Vacation”. When used with --directory
, this would result in the photo being exported to more than one directory (thus more than one copy of the photo would be exported). For example, if IMG_1234.JPG
has keywords Travel
, and Vacation
and you run the following command:
osxphotos export /path/to/export --directory "{keyword}"
the exported files would be:
/path/to/export/Travel/IMG_1234.JPG
/path/to/export/Vacation/IMG_1234.JPG
If your photos are organized in folders and albums in Photos you can preserve this structure on export by using the {folder_album}
template field with the --directory
option. For example, if you have a photo in the album Vacation
which is in the Travel
folder, the following command would export the photo to the Travel/Vacation
directory:
osxphotos export /path/to/export --directory "{folder_album}"
Photos can belong to more than one album. In this case, the template field {folder_album}
will expand to all the album names that the photo belongs to. For example, if a photo belongs to the albums Vacation
and Travel
, the template field {folder_album}
would expand to Vacation
, Travel
. If the photo belongs to no albums, the template field {folder_album}
would expand to “_” (the default value).
All template fields including {folder_album}
can be further filtered using a number of different filters. To convert all directory names to lower case for example, use the lower
filter:
osxphotos export /path/to/export --directory "{folder_album|lower}"
If all your photos were organized into various albums under a folder named Events
but some where also included in other top-level albums and you wanted to export only the Events
folder, you could use the filter
option to filter out the other top-level albums by selecting only those folder/album paths that start with Events
:
osxphotos export /path/to/export --directory "{folder_album|filter(startswith Events)}"
You can learn more about the other filters using osxphotos help export
.
Specify exported filename
By default, osxphotos will use the original filename of the photo when exporting. That is, the filename the photo had when it was taken or imported into Photos. This is often something like IMG_1234.JPG
or DSC05678.dng
. osxphotos allows you to specify a custom filename template using the --filename
option in the same way as --directory
allows you to specify a custom directory name. For example, Photos allows you specify a title or caption for a photo and you can use this in place of the original filename:
osxphotos export /path/to/export --filename "{title}"
The above command will export photos using the title. Note that you don’t need to specify the extension as part of the --filename
template as osxphotos will automatically add the correct file extension. Some photos might not have a title so in this case, you could use the default value feature to specify a different name for these photos. For example, to use the title as the filename, but if no title is specified, use the original filename instead:
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 <──────┘
The osxphotos template system also allows for limited conditional logic of the type "If a condition is true then do one thing, otherwise, do a different thing". For example, you can use the --filename
option to name files that are marked as "Favorites" in Photos differently than other files. For example, to add a "#" to the name of every photo that's a favorite:
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
Like with --directory
, using a multi-valued template field such as {keyword}
may result in more than one copy of a photo being exported. For example, if IMG_1234.JPG
has keywords Travel
, and Vacation
and you run the following command:
osxphotos export /path/to/export --filename "{keyword}-{original_name}"
the exported files would be:
/path/to/export/Travel-IMG_1234.JPG
/path/to/export/Vacation-IMG_1234.JPG
Edited photos
If a photo has been edited in Photos (e.g. cropped, adjusted, etc.) there will be both an original image and an edited image in the Photos Library. By default, osxphotos will export both the original and the edited image. To distinguish between them, osxphotos will append "_edited" to the edited image. For example, if the original image was named IMG_1234.JPG
, osxphotos will export the original as IMG_1234.JPG
and the edited version as IMG_1234_edited.jpeg
. Note: Photos changes the extension of edited images to ".jpeg" even if the original was named ".JPG". You can change the suffix appended to edited images using the --edited-suffix
option:
osxphotos export /path/to/export --edited-suffix "_EDIT"
In this example, the edited image would be named IMG_1234_EDIT.jpeg
. Like many options in osxphotos, the --edited-suffix
option can evaluate an osxphotos template string so you could append the modification date (the date the photo was edited) to all edited photos using this command:
osxphotos export /path/to/export --edited-suffix "_{modified.year}-{modified.mm}-{modified.dd}"
In this example, if the photo was edited on 21 April 2021, the name of the exported file would be: IMG_1234_2021-04-21.jpeg
.
You can tell osxphotos to not export edited photos (that is, only export the original unedited photos) using --skip-edited
:
osxphotos export /path/to/export --skip-edited
You can also tell osxphotos to export either the original photo (if the photo has not been edited) or the edited photo (if it has been edited), but not both, using the --skip-original-if-edited
option:
osxphotos export /path/to/export --skip-original-if-edited
As mentioned above, Photos renames JPEG images that have been edited with the ".jpeg" extension. Some applications use ".JPG" and others use ".jpg" or ".JPEG". You can use the --jpeg-ext
option to have osxphotos rename all JPEG files with the same extension. Valid values are jpeg, jpg, JPEG, JPG; e.g. --jpeg-ext jpg
to use '.jpg' for all JPEGs.
osxphotos export /path/to/export --jpeg-ext jpg
Specifying the Photos library
All the above commands operate on the default Photos library. Most users only use a single Photos library which is also known as the System Photo Library. It is possible to use Photos with more than one library. For example, if you hold down the "Option" key while opening Photos, you can select an alternate Photos library. If you don't specify which library to use, osxphotos will try find the last opened library. Occasionally it can't determine this and in that case, it will use the System Photos Library. If you use more than one Photos library and want to explicitly specify which library to use, you can do so with the --db
option. (db is short for database and is so named because osxphotos operates on the database that Photos uses to manage your Photos library).
osxphotos export /path/to/export --db ~/Pictures/MyAlternateLibrary.photoslibrary
Missing photos
osxphotos works by copying photos out of the Photos library folder to export them. You may see osxphotos report that one or more photos are missing and thus could not be exported. One possible reason for this is that you are using iCloud to synch your Photos library and Photos either hasn't yet synched the cloud library to the local Mac or you have Photos configured to "Optimize Mac Storage" in Photos Preferences. Another reason is that even if you have Photos configured to download originals to the Mac, Photos does not always download photos from shared albums or original screenshots to the Mac.
If you encounter missing photos you can tell osxphotos to download the missing photos from iCloud using the --download-missing
option. --download-missing
uses AppleScript to communicate with Photos and tell it to download the missing photos. Photos' AppleScript interface is somewhat buggy and you may find that Photos crashes. In this case, osxphotos will attempt to restart Photos to resume the download process. There's also an experimental --use-photokit
option that will communicate with Photos using a different "PhotoKit" interface. This option must be used together with --download-missing
:
osxphotos export /path/to/export --download-missing
osxphotos export /path/to/export --download-missing --use-photokit
Exporting to external disks
If you are exporting to an external network attached storage (NAS) device, you may encounter errors if the network connection is unreliable. In this case, you can use the --retry
option so that osxphotos will automatically retry the export. Use --retry
with a number that specifies the number of times to retry the export:
osxphotos export /path/to/export --retry 3
In this example, osxphotos will attempt to export a photo up to 3 times if it encounters an error.
In addition to --retry
, the --exportdb
and --ramdb
may improve performance when exporting to an external disk or a NAS. When osxphotos exports photos, it creates an export database file named .osxphotos_export.db
in the export folder which osxphotos uses to keep track of which photos have been exported. This allows you to restart and export and to use --update
to update an existing export. If the connection to the export location is slow or flaky, having the export database located on the export disk may decrease performance. In this case, you can use --exportdb DBPATH
to instruct osxphotos to store the export database at DBPATH. If using this option, I recommend putting the export database on your Mac system disk (for example, in your home directory). If you intend to use --update
to update the export in the future, you must remember where the export database is and use the --exportdb
option every time you update the export.
Another alternative to using --exportdb
is to use --ramdb
. This option instructs osxphotos to use a RAM database instead of a file on disk. The RAM database is much faster than the file on disk and doesn't require osxphotos to access the network drive to query or write to the database. When osxphotos completes the export it will write the RAM database to the export location. This can offer a significant performance boost but you will lose state information if osxphotos crashes or is interrupted during export.
Exporting metadata with exported photos
Photos tracks a tremendous amount of metadata associated with photos in the library such as keywords, faces and persons, reverse geolocation data, and image classification labels. Photos' native export capability does not preserve most of this metadata. osxphotos can, however, access and preserve almost all the metadata associated with photos. Using the free exiftool
app, osxphotos can write metadata to exported photos. Follow the instructions on the exiftool website to install exiftool then you can use the --exiftool
option to write metadata to exported photos:
osxphotos export /path/to/export --exiftool
This will write basic metadata such as keywords, persons, and GPS location to the exported files. osxphotos includes several additional options that can be used in conjunction with --exiftool
to modify the metadata that is written by exiftool
. For example, you can use the --keyword-template
option to specify custom keywords (again, via the osxphotos template system). For example, to use the folder and album a photo is in to create hierarchical keywords in the format used by Lightroom Classic:
│ │
│ │
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">
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
The above command will write all the regular metadata that --exiftool
normally writes to the file upon export but will also add an additional keyword in the exported metadata in the form "Folder1>Folder2>Album". If you did not include the (>)
in the template string (e.g. {folder_album}
), folder_album would render in form "Folder1/Folder2/Album".
A powerful feature of Photos is that it uses machine learning algorithms to automatically classify or label photos. These labels are used when you search for images in Photos but are not otherwise available to the user. osxphotos is able to read all the labels associated with a photo and makes those available through the template system via the {label}
. Think of these as automatic keywords as opposed to the keywords you assign manually in Photos. One common use case is to use the automatic labels to create new keywords when exporting images so that these labels are embedded in the image's metadata:
osxphotos export /path/to/export --exiftool --keyword-template "{label}"
Removing a keyword during export
If some of your photos contain a keyword you do not want to be added to the exported file with --exiftool
, you can use the template system to remove the keyword from the exported file. For example, if you want to remove the keyword "MyKeyword" from all your photos:
osxphotos export /path/to/export --exiftool --keyword-template "{keyword|remove(MyKeyword)}" --replace-keywords
In this example, |remove(MyKeyword)
is a filter which removes MyKeyword
from the keyword list of every photo being processed. The --replace-keywords
option instructs osxphotos to replace the keywords in the exported file with the filtered keywords from --keyword-template
.
Note: When evaluating templates for --directory
and --filename
, osxphotos inserts the automatic default value "_" for any template field which is null (empty or blank). This is to ensure that there's never a null directory or filename created. For metadata templates such as --keyword-template
, osxphotos does not provide an automatic default value thus if the template field is null, no keyword would be created. Of course, you can provide a default value if desired and osxphotos will use this. For example, to add "nolabel" as a keyword for any photo that doesn't have labels:
osxphotos export /path/to/export --exiftool --keyword-template "{label,nolabel}"
Sidecar files
Another way to export metadata about your photos is through the use of sidecar files. These are files that have the same name as your photo (but with a different extension) and carry the metadata. Many digital asset management applications (for example, PhotoPrism, Lightroom, Digikam, etc.) can read or write sidecar files. osxphotos can export metadata in exiftool compatible JSON and XMP formats using the --sidecar
option. For example, to output metadata to XMP sidecars:
osxphotos export /path/to/export --sidecar XMP
Unlike --exiftool
, you do not need to install exiftool to use the --sidecar
feature. Many of the same configuration options that apply to --exiftool
to modify metadata, for example, --keyword-template
can also be used with --sidecar
.
Sidecar files are named "photoname.ext.sidecar_ext". For example, if the photo is named IMG_1234.JPG
and the sidecar format is XMP, the sidecar would be named IMG_1234.JPG.XMP
. Some applications expect the sidecar in this case to be named IMG_1234.XMP
. You can use the -sidecar-drop-ext
option to force osxphotos to name the sidecar files in this manner:
osxphotos export /path/to/export --sidecar XMP -sidecar-drop-ext
Updating a previous export
If you want to use osxphotos to perform periodic backups of your Photos library rather than a one-time export, use the --update
option. When osxphotos export
is run, it creates a database file named .osxphotos_export.db
in the export folder. (Note Because the filename starts with a ".", you won't see it in Finder which treats "dot-files" like this as hidden. You will see the file in the Terminal.) . If you run osxphotos with the --update
option, it will look for this database file and, if found, use it to retrieve state information from the last time it was run to only export new or changed files. For example:
osxphotos export /path/to/export --update
will read the export database located in /path/to/export/.osxphotos_export.db
and only export photos that have been added or changed since the last time osxphotos was run. You can run osxphotos with the --update
option even if it's never been run before. If the database isn't found, osxphotos will create it. If you run osxphotos export
without --update
in a folder where you had previously exported photos, it will re-export all the photos. If your intent is to keep a periodic backup of your Photos Library up to date with osxphotos, you should always use --update
.
If your workflow involves moving files out of the export directory (for example, you move them into a digital asset management app) but you want to use the features of --update
, you can use the --only-new
with --update
to force osxphotos to only export photos that are new (added to the library) since the last update. In this case, osxphotos will ignore the previously exported files that are now missing. Without --only-new
, osxphotos would see that previously exported files are missing and re-export them.
osxphotos export /path/to/export --update --only-new
If your workflow involves editing the images you exported from Photos but you still want to maintain a backup with --update
, you should use the --ignore-signature
option. --ignore-signature
instructs osxphotos to ignore the file's signature (for example, size and date modified) when deciding which files should be updated with --update
. If you edit a file in the export directory and then run --update
without --ignore-signature
, osxphotos will see that the file is different than the one in the Photos library and re-export it.
osxphotos export /path/to/export --update --ignore-signature
Dry Run
You can use the --dry-run
option to have osxphotos "dry run" or test an export without actually exporting any files. When combined with the --verbose
option, which causes osxphotos to print out details of every file being exported, this can be a useful tool for testing your export options before actually running a full export. For example, if you are learning the template system and want to verify that your --directory
and --filename
templates are correct, --dry-run --verbose
will print out the name of each file being exported.
osxphotos export /path/to/export --dry-run --verbose
Creating a report of all exported files
You can use the --report
option to create a report, in comma-separated values (CSV) format that will list the details of all files that were exported, skipped, missing, etc. This file format is compatible with programs such as Microsoft Excel. Provide the name of the report after the --report
option:
osxphotos export /path/to/export --report export.csv
You can also create reports in JSON or SQLite format by changing the extension of the report filename. For example, to create a JSON report:
osxphotos export /path/to/export --report export.json
And to create a SQLite report:
osxphotos export /path/to/export --report export.sqlite
Exporting only certain photos
By default, osxphotos will export your entire Photos library. If you want to export only certain photos, osxphotos provides a rich set of "query options" that allow you to query the Photos database to filter out only certain photos that match your query criteria. The tutorial does not cover all the query options as there are over 50 of them--read the help text (osxphotos help export
) to better understand the available query options. No matter which subset of photos you would like to export, there is almost certainly a way for osxphotos to filter these. For example, you can filter for only images that contain certain keywords or images without a title, images from a specific time of day or specific date range, images contained in specific albums, etc.
For example, to export only photos with keyword Travel
:
osxphotos export /path/to/export --keyword "Travel"
Like many options in osxphotos, --keyword
(and most other query options) can be repeated to search for more than one term. For example, to find photos with keyword Travel
or keyword Vacation
:
osxphotos export /path/to/export --keyword "Travel" --keyword "Vacation"
To export only photos contained in the album "Summer Vacation":
osxphotos export /path/to/export --album "Summer Vacation"
In Photos, it's possible to have multiple albums with the same name. In this case, osxphotos would export photos from all albums matching the value passed to --album
. If you wanted to export only one of the albums and this album is in a folder, the --regex
option (short for "regular expression"), which does pattern matching, could be used with the {folder_album}
template to match the specific album. For example, if you had a "Summer Vacation" album inside the folder "2018" and also one with the same name inside the folder "2019", you could export just the album "2018/Summer Vacation" using this command:
osxphotos export /path/to/export --regex "2018/Summer Vacation" "{folder_album}"
This command matches the pattern "2018/Summer Vacation" against the full folder/album path for every photo.
There are also a number of query options to export only certain types of photos. For example, to export only photos taken with iPhone "Portrait Mode":
osxphotos export /path/to/export --portrait
You can also export photos in a certain date range:
osxphotos export /path/to/export --from-date "2020-01-01" --to-date "2020-02-28"
or photos added to the library in the last week:
osxphotos export /path/to/export --added-in-last "1 week"
Converting images to JPEG on export
Photos can store images in many different formats. osxphotos can convert non-JPEG images (for example, RAW photos) to JPEG on export using the --convert-to-jpeg
option. You can specify the JPEG quality (0: worst, 1.0: best) using --jpeg-quality
. For example:
osxphotos export /path/to/export --convert-to-jpeg --jpeg-quality 0.9
Finder attributes
In addition to using exiftool
to write metadata directly to the image metadata, osxphotos can write certain metadata that is available to the Finder and Spotlight but does not modify the actual image file. This is done through something called extended attributes which are stored in the filesystem with a file but do not actually modify the file itself. Finder tags and Finder comments are common examples of these.
osxphotos can, for example, write any keywords in the image to Finder tags so that you can search for images in Spotlight or the Finder using the tag:tagname
syntax:
osxphotos export /path/to/export --finder-tag-keywords
--finder-tag-keywords
also works with --keyword-template
as described above in the section on exiftool
:
osxphotos export /path/to/export --finder-tag-keywords --keyword-template "{label}"
The --xattr-template
option allows you to set a variety of other extended attributes. It is used in the format --xattr-template ATTRIBUTE TEMPLATE
where ATTRIBUTE is one of 'authors','comment', 'copyright', 'description', 'findercomment', 'headline', 'keywords'.
For example, to set Finder comment to the photo's title and description:
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.
Saving and loading options
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
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.
Run commands on exported photos for post-processing
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:
│└───> if no keywords, insert nothing (empty 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.
An example from an actual osxphotos user
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 --db /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
Color Themes
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.
Conclusion
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.
Command line reference: export
osxphotos help export
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'. --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. See https://github.com/RhetTbull/os xphotos/blob/master/examples/query_function.py for example of how to use this option. --missing Export only photos missing from the Photos library; must be used with --download-missing. --deleted Include photos from the 'Recently Deleted' folder. --deleted-only Include only 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. --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] --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. --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'. --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. --keep KEEP_PATH When used with --cleanup, prevents file or directory KEEP_PATH 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_PATH may be a file path, e.g. '/Volumes/Photos/keep.jpg', or a file path and wild card, e.g. '/Volumes/Photos/*.txt', or a directory, e.g. '/Volumes/Photos/KeepMe'. KEEP_PATH may be an absolute path or a relative path. If it is relative, it must be relative to the export destination. For example if export destination is `/Volumes/Photos` and you want to keep all `.txt` files, you can specify `--keep "/Volumes/Photos/*.txt"` or `--keep "*.txt"`. If wild card is used, KEEP_PATH must be enclosed in quotes to prevent the shell from expanding the wildcard, e.g. `--keep "/Volumes/Photos/*.txt"`. If KEEP_PATH is a directory, all files and directories contained in KEEP_PATH will be kept. --keep may be repeated to keep additional files/directories. --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. This feature is currently experimental. I don't know how well it will work on large export sets. --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. This feature is currently experimental. I don't know how well it will work on large export sets. --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. This feature is currently experimental. I don't know how well it will work on large export sets. --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 Post
Command below.
--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. 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;
may improve performance when exporting over a
network or slow disk but could result in
losing update state information if the program
is interrupted or crashes.
--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.
--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
'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 --verbose
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?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'].
• 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 o=:>
──┘───────┘─────────────┘││ ──────┘│ ──────┘ code>