Skip to main content
Participant
December 22, 2022
Open for Voting

P: Add SDK support for moving photos between folders in the catalog

  • December 22, 2022
  • 8 replies
  • 444 views

When using the Lightroom Classic SDK it would be great to be able to move photos in the catalog between folders programmatically.

 

A simple example would be for writing a plugin that moves selected photos between parent catalog folders, while maintainig folder structure (to move files between disks).

 

While it is possible to create folders and move disk files using `LrFileUtils`, any catalog photo moved that way ends up as 'missing' in the catalog because their disk location is changed by `LrFileUtils` but the photo `path` in the catalog is not updated.

 

It is possible to read a photo's path using `photo:getRawMetadata("path")`, provided by `LrPhoto`, but it is not possible to change a photo's path using `photo:setRawMetadata("path")` because `path` is not a valid key for writing back to the catalog photo.

 

So in summary, it is currently not possible to move a photo between catalog folders in a Lightroom Classic catalog using the SDK.

 `LrFileUtils` does not update the photo path in the catalog upon moving it on disk, and `LrPhoto` can't be used to update a photo path on disk using the SDK.

 

Please consider adding support for that operation to the SDK.

Thank you.

8 replies

johnrellis
Legend
September 17, 2026

One possible way of moving a photo to another folder (which only became possible starting with LR 14.3):

 

1. Save the photo’s metadata to disk using the long-undocumented photo:saveMetadata().  It’s been present for many, many years.

 

2. Use catalog:getTargetPhoto() and :getTargetPhotos() to save the current selection and then set the selection to the photos to be moved.

 

3. Use LrSelection.removeFromCatalog() to remove the selected photos from the catalog.

 

4. Use LrFileUtils.move() to move the photos, along with any .xmp and .acr sidecars, to the target folder.

 

5. Use catalog:addPhoto() to import the photos into the catalog from their new location.

 

Note that the SDK is riddled with race conditions and undocumented asynchrony. Here is the utility function many of my plugins use to safely save a photo’s metadata to disk:

--[[----------------------------------------------------------------------------
public string path, string err
saveMetadata (LrPhoto photo)

Initiates a Metadata > Save Metadata To File for the photo and waits for up
to 10 seconds for it complete. Ignores videos and virtual copies.

Returns in "path" the file to which the metadata was saved (a .xmp for
raws, nil for videos and virtual copies, the photo file itself otherwise).

If a photo can't be saved, returns an error message in "err".

Starting in LR 15, photo:saveMetadata() can return before saving to disk.
This might have occurred many years previously, not sure, but it didn't
occur in LR 14.
------------------------------------------------------------------------------]]

function Util.saveMetadata (photo)
local fileFormat = photo:getRawMetadata ("fileFormat")
local isVirtualCopy = photo:getRawMetadata ("isVirtualCopy")
if fileFormat == "VIDEO" or isVirtualCopy then return nil, nil end

local function returnErr (err)
local msg = Util.logError ("Couldn't save metadata to file: %s\n%s",
photo.path, err)
return photo.path, msg
end

--[[ Sometimes photo:saveMetadata() fails with an obscure
error, perhaps because of a race inside LR. Retrying
for up to 10 seconds seems to reduce the occurrences. ]]
local startTime = currentTime ()
for i = 1, math.huge do
local success, err = LrTasks.pcall (photo.saveMetadata, photo)
if success then
if i > 1 then
Debug.logn ("Util.saveMetadata:", i,
"tries needed for successful save", photo.path)
end
break
end
if i >= 10 and not success then return returnErr (err) end
LrTasks.sleep (1)
end

--[[ Starting in LR 15, photo:saveMetadata () is asynchronous.
Wait until we observe the file's modification time changes. ]]
local paths = fileFormat ~= "RAW" and {photo.path} or
{removeExtension (photo.path) .. ".xmp",
photo.path .. "_xmp"}

local delay, waitTime, maxWaitTime = 0.01, 0, 5
while true do
if currentTime () > startTime + maxWaitTime then
return returnErr ("Timed out")
end

for _, path in ipairs (paths) do
local modTime = fileAttributes (path).fileModificationDate or 0
if modTime >= startTime then
if waitTime > 0 then
Util.logError ("Util.saveMetadata wait: %g secs %s",
waitTime, path)
end
return path, nil
end
end

LrTasks.sleep (delay)
waitTime = waitTime + delay
delay = math.min (delay * 1.5, 0.2)
end


return path, nil
end

 

 

Participant
September 17, 2026

Brilliant - thanks for that, now able to move images without leaving the horrible missing files behind. 10 out of 10 🤙

Participant
September 17, 2026

Really need this - not sure why the request has been open for more than 3 years

johnrellis
Legend
September 17, 2026

[View this post in your web browser. It contains formatting and images that don't appear in email.]

​@PCorley not sure why the request has been open for more than 3 years

 

Since LR 4, Adobe has invested only sporadically in the SDK. As far as I know, LR 4 was the last version for which there was a dedicated truly senior engineer working on the SDK.  The reletively small changes that have been added since LR 4 sometimes have clearly been designed and added by a junior engineer (e.g. removing a photo from the catalog via LrSelection rather than LrPhoto or LrCatalog).

Participant
September 17, 2026

Pity - we still have to pay for Lightroom, but seems they don’t have to maintain one of the facilities that make this better than the competition (i.e., plugins !)

KerdosMedia
Known Participant
January 15, 2025

I could really use the move feature as well.

Participant
October 5, 2023

While finally automating our complete Lightroom workflow top to bottom, I now discover there is no photo:move() and photo:delete().

I am so extremely dissappointed right now. For what reason could these functions be possible missing from the SDK?

johnrellis
Legend
December 22, 2022

There was a years-old feature request for this (and to delete photos from the catalog) in the old feedback forum, but apparently it didn't get copied over when Adobe transitioned to the new forum platform.