Become a MacRumors Supporter for $25/year with no ads, private forums, and more!

Mac Applescript: Delete folder in Photos App

Alwis

macrumors member
Original poster
Jan 12, 2017
93
30
Hi,

I can not figure out the following problem, but I am quite new to Applescript, so this might be a stupid question.

I want to delete empty folders and so far managed to identify them with the following script, which is mostly "copy&paste" from the internet:

Code:
set allfolders to {}
set allalbums to {}


tell application "Photos"
    
    set allalbums to the albums --  collect all albums
    set allfoldernames to {}
    set allalbumnames to {}
    set allfolders to {}
    
    
    set level to 0 -- nesting level of folders
    
    set nextlevelFolders to the folders of folder "TestScript"
    set currentLevelFolders to {}
    
    repeat while (nextlevelFolders is not {})
        set currentLevelFolders to nextlevelFolders
        set nextlevelFolders to {}
        repeat with fi in currentLevelFolders
            tell fi
                set ffolders to its folders
                set falbums to its albums
                set fcontainers to its containers
                set nextlevelFolders to ffolders & nextlevelFolders
                set allalbums to falbums & allalbums
            end tell
            
            if (fcontainers is {}) then
                set folderName to the name of fi
                log {"Folder is empty", folderName}
                delete folder id fi
            end if
        end repeat
        set allfolders to currentLevelFolders & allfolders
        
        
        
        set level to level + 1
    end repeat

What is not working is the delete part...

I tried

Code:
delete folder fi

Which results in a "can not converted to integer error:
error "„Photos“ hat einen Fehler erhalten: folder id \"1ADB1EED-869A-429E-B688-84D6E56FEE2D/L0/020\" of folder id \"101C1EEB-96A5-45A6-87CD-72C813CB3BD4/L0/020\" of folder id \"88BC73E2-B297-4304-AE0E-7AC910FF6C00/L0/020\" kann nicht in Typ integer umgewandelt werden." number -1700 from folder id "1ADB1EED-869A-429E-B688-84D6E56FEE2D/L0/020" of folder id "101C1EEB-96A5-45A6-87CD-72C813CB3BD4/L0/020" of folder id "88BC73E2-B297-4304-AE0E-7AC910FF6C00/L0/020" to integ

Code:
delete folder id (fi's id)

That results in a "can not be read error:
error "„Photos“ hat einen Fehler erhalten: „folder id \"1ADB1EED-869A-429E-B688-84D6E56FEE2D/L0/020\"“ kann nicht gelesen werden." number -1728 from folder id "1ADB1EED-869A-429E-B688-84D6E56FEE2D/L0/020"


I tried some variations of the above, but I always get error -1700 or -1728


Probably this is only some small thing, but I can not figure it out. Maybe you have any ideas, what is going wrong?

Thanks for your help!

Alwis
 

Mark FX

macrumors regular
Nov 18, 2011
132
14
West Sussex, UK
I've never scripted the "Photos" app before.
But your posted code is a bit of a mess on first look.

So this is just a guess.

But try replacing.

Code:
delete folder id fi

With

Code:
delete fi


Regrads Mark
 
Last edited:

Alwis

macrumors member
Original poster
Jan 12, 2017
93
30
Hi Mark,

thanks for your help.

But your posted code is a bit of a mess on first look.

I know, that is one of my first apple scripts and a lot of trial & error...


But try replacing.

That results in the following "can not be read error"

Code:
error "„Photos“ hat einen Fehler erhalten: „folder id \"1ADB1EED-869A-429E-B688-84D6E56FEE2D/L0/020\" of folder id \"101C1EEB-96A5-45A6-87CD-72C813CB3BD4/L0/020\" of folder id \"88BC73E2-B297-4304-AE0E-7AC910FF6C00/L0/020\"“ kann nicht gelesen werden." number -1728 from folder id "1ADB1EED-869A-429E-B688-84D6E56FEE2D/L0/020" of folder id "101C1EEB-96A5-45A6-87CD-72C813CB3BD4/L0/020" of folder id "88BC73E2-B297-4304-AE0E-7AC910FF6C00/L0/020"
 

Mark FX

macrumors regular
Nov 18, 2011
132
14
West Sussex, UK
The only other suggestion I can make is putting a delay after the "delete" command.
The reason for this is that you have to allow time for the Photos application to carry out the instruction.
Especially when sending commands in repeat loops, as the the commands end up being sent quicker than can be handled by the application.

Code:
delete fi
delay 2.0  -- 2 second delay


When scripting other applications with AppleScript, it's well known that you have to give time for the application to respond and carry out instructions, and you achieve this with the AppleScript "delay" command.
I'm not saying this is the problem with your script, but this should be done anyway as a matter of course.

Having never scripted the Photos application myself, I can't see exactly whats wrong with your code.
But if I find time, I shall have a go at scripting it myself, and see what I can learn.

Regards Mark
 

Origin41

macrumors newbie
Oct 14, 2020
14
3
Mark.

Pls forgive Me but if he's a n00b isn't it..

Code:
Suso su <insert login>
delete fi
delay 2.0 -- 2 second delay

Regards

Dan

P.S: not going to accomplish much as an unauth user

@Alwis - filing permissions?

This is UNIX not Linux! & it's a carnivore.. It's a big cat! Pun intended!

If it's simply the case of trying to mobile me.. Eh app/delete..
 
Last edited:

Mark FX

macrumors regular
Nov 18, 2011
132
14
West Sussex, UK
To Alwis

I finally got a moment to try out some AppleScript code in the Photos application.
And this is what i've come up, it deletes all empty folders including the top level folders as well.
So if you don't want the top level folders touched, then let me know and I'll post a modified script.

AppleScript:
tell application id "com.apple.photos"
    activate
    delay 2.0
    set scriptResult to return as text
    set everyFolder to every folder as list
    set everyFolderCount to (count of everyFolder) as integer
    set emptyFoldersDeleted to false as boolean
    set emptyFoldersProcessed to 0 as integer
    repeat until emptyFoldersDeleted
        repeat with theFolder in everyFolder
            set theFolderName to theFolder's name
            if theFolder's parent = missing value then -- Top Level Folders of Containers
                if theFolder's containers = {} then
                    delete theFolder -- Delete Empty Top Level Folders
                    --delay 1.0 -- Delay for Photos Application Response
                    set emptyFoldersProcessed to emptyFoldersProcessed - 1
                    set scriptResult to scriptResult & "Top Level Folder " & theFolderName & " Empty so Deleted" & return
                else
                    set emptyFoldersProcessed to emptyFoldersProcessed + 1
                    set scriptResult to scriptResult & "Top Level Folder " & theFolderName & " Not Empty so Kept" & return
                end if
            else -- Sub Level Folders of Top Level Folders
                if theFolder's containers = {} then
                    delete theFolder -- Delete Empty Sub Level Folder
                    --delay 1.0 -- Delay for Photos Application Response
                    set emptyFoldersProcessed to emptyFoldersProcessed - 1
                    set scriptResult to scriptResult & "Sub Level Folder " & theFolderName & " Empty so Deleted" & return
                else
                    set emptyFoldersProcessed to emptyFoldersProcessed + 1
                    set scriptResult to scriptResult & "Sub Level Folder " & theFolderName & " Not Empty so Kept" & return
                end if
            end if
        end repeat
        set everyFolder to every folder as list -- Reset everyFolder Variable After Deletions
        --delay 1.0 -- Delay for Photos Application Response
        if emptyFoldersProcessed = everyFolderCount then
            set emptyFoldersDeleted to true
        end if
    end repeat
    return scriptResult
end tell

You will notice that I've commented out the delay commands, but you may need them.
Depending how large you folder tree structure is, and how fast your system operates with other active processes.

You can also delete any references to the "scriptResult" variable if your not interested in the script's result message.

Hope this helps

Regards Mark
 
Last edited:
  • Like
Reactions: Alwis

Alwis

macrumors member
Original poster
Jan 12, 2017
93
30
Hi Mark,

thanks a lot for your work and the great help!! That is much more than what I hopped to get by asking here! I will try this out tomorrow!

Alwis
 

Alwis

macrumors member
Original poster
Jan 12, 2017
93
30
Hi Mark,

thanks again for your effort 👍

Today I tried out your script. It deletes the empty folders at the top level, but not somewhere down in the hierarchy, probably because "set everyFolder to every folder as list" only returns the folders at the top level.

But it made me wondering, why your delete succeeded and mine not. I did some more testing with the delete command:

Deleting a top level folder works as expected, with the folder id as argument, e.g.:
Code:
delete "88BC73E2-B297-4304-AE0E-7AC910FF6C00/L0/020"


But deleting a subfolder does not succeed, no matter which argument I tried, e.g.:
Code:
 delete folder "1ADB1EED-869A-429E-B688-84D6E56FEE2D/L0/020" of folder id "101C1EEB-96A5-45A6-87CD-72C813CB3BD4/L0/020" of folder id "88BC73E2-B297-4304-AE0E-7AC910FF6C00/L0/020"


In theory the id of the sub-folder should be enough, as it is unique to the folder, but this does not work either:
Code:
delete "1ADB1EED-869A-429E-B688-84D6E56FEE2D/L0/020"


For reference, the complete hierarchy, as reported by the Photo App is:
Code:
folder id \"1ADB1EED-869A-429E-B688-84D6E56FEE2D/L0/020\" of folder id \"101C1EEB-96A5-45A6-87CD-72C813CB3BD4/L0/020\" of folder id \"88BC73E2-B297-4304-AE0E-7AC910FF6C00/L0/020\"


Currently I am not sure if I specify the sub folder in a wrong way or if this might be a bug...

Alwis
 

Mark FX

macrumors regular
Nov 18, 2011
132
14
West Sussex, UK
Hi Alwis

Firstly your a correct in saying that scripting the Photos app is very buggy, that's something I noticed when trying out different types of script.
There is a scripting definition file for Photos.
You can get at it from the Script Editor "Window" then "Library" menu items, if it's not there already, then click the "+" button, and then goto the Applications folder and select the Photos Application, then you can open and browse the scripting def. file.

Secondly I do not find as you do, you say that "set everyFolder to every folder as list" gives you a list of only top level folders, but on my system this code will contain every Photos app folder from the top to the bottom levels.
So it sounds like we may be dealing with different versions of the Photos application, or different operating system versions, because AppleScript does change with new OS releases.
I'm on OSX 10.13, with a Photos application version 3.0, so if your on different versions than me, then my help would be fairly useless.

Thirdly I found working with the container id's gets a bit messy, so if you want to delete an item, wether that be an Album or Folder, I found that just refering to it as an item reference like this is simplest.

AppleScript:
set everyFolder to every folder as list
repeat with theFolder in everyFolder
    if theFolder's containers = {} then -- Folder is Empty
        delete the theFolder -- a Reference to the Folder
    end if
end repeat


If you copy and paste the code as is written, I found it worked fine for me, although I never created a very complex folder tree structure, just 10 to 15 folders in a small tree.
So using it on a complex 100 or more folder tree, may be more problematic.
But in theory it should still work, but you may need to uncomment the "delay 1.0" statements.

if you don't want to touch the top level folders simply change the code to this.

AppleScript:
tell application id "com.apple.photos"
    activate
    delay 2.0
    set scriptResult to return as text
    set everyFolder to every folder as list
    set everyFolderCount to (count of everyFolder) as integer
    set emptyFoldersDeleted to false as boolean
    set emptyFoldersProcessed to 0 as integer
    repeat until emptyFoldersDeleted
        repeat with theFolder in everyFolder
            set theFolderName to theFolder's name
            if theFolder's parent = missing value then -- Top Level Folders of Containers
                    set emptyFoldersProcessed to emptyFoldersProcessed + 1
                    set scriptResult to scriptResult & "Top Level Folder " & theFolderName & " Untouched" & return
            else -- Sub Level Folders of Top Level Folders
                if theFolder's containers = {} then
                    delete theFolder -- Delete Empty Sub Level Folder
                    --delay 1.0 -- Delay for Photos Application Response
                    set emptyFoldersProcessed to emptyFoldersProcessed - 1
                    set scriptResult to scriptResult & "Sub Level Folder " & theFolderName & " Empty so Deleted" & return
                else
                    set emptyFoldersProcessed to emptyFoldersProcessed + 1
                    set scriptResult to scriptResult & "Sub Level Folder " & theFolderName & " Not Empty so Kept" & return
                end if
            end if
        end repeat
        set everyFolder to every folder as list -- Reset everyFolder Variable After Deletions
        --delay 1.0 -- Delay for Photos Application Response
        if emptyFoldersProcessed = everyFolderCount then
            set emptyFoldersDeleted to true
        end if
    end repeat
    return scriptResult
end tell


I hope the code I posted gives you enough to work and play around with as a start.
My code is certaiinly not a complete applet, I did not include any error checking for one, which is something you should learn to incorporate into your scripts.
The very basic error checking in AppleScript looks something like this.

AppleScript:
try
    -- Code that might cause an error goes here, like a delete command.
on error
    -- Handle the Error here, maybe by displaying an error message box.
end try

-- OR

try
    set theVariable to "This text" as real -- This Line Causes an Error
on error errorMessage number errorNumber from errorObject
    return (errorMessage & return & errorNumber & return & errorObject) -- Handle the Error
end try


There are certainly a lot of other possabilities to scripting the Photos application, but I'll leave it to you to experiment.
Accessing the scripting definition file might help you a lot more with understanding the scriptable items in the app.
But like all coding, it is simply trial and error and experimenting with code.
There is a lot of help to be found online when it comes to AppleScript, simply search the interweb.
There's even a dedicated AppleScript forum to be found, that has a lot of knowledgable AppleScript experts.

Hope I've helped to some degree.

Regards Mark
 
Last edited:

Mark FX

macrumors regular
Nov 18, 2011
132
14
West Sussex, UK
Hey Alwis

It may also interest you to know that the code below also works for me.

AppleScript:
set everyFolderID to id of every folder as list
repeat with folderID in everyFolderID
    if containers of folder id folderID = {} then
        delete folder id folderID
    end if
end repeat


And this also works, although I can't see why you would use it this way.

AppleScript:
delete folder id "wRQz2RhhQESkOFmjlKejnw"


But that assumes your on the same software versions to me.

Hope that clarifies a few things for you.

Regards Mark
 
Last edited:
  • Like
Reactions: Alwis

Alwis

macrumors member
Original poster
Jan 12, 2017
93
30
Hi Mark,

thanks again for your great effort!! 👍👍👍

I am on Catalina 10.15.7, maybe that explains the different behavior...

I will give it an other try tomorrow and report back any new findings. I am not sure, but I might still have a VM with High Sierra, then I could try this out with the same version as yours.

Alwis
 

Mark FX

macrumors regular
Nov 18, 2011
132
14
West Sussex, UK
Hi Alwis

the later operating system would explain a lot, that is why were getting different results.
I would suspect that the Photos app version is also different.

So I'll leave it to you to experiment further, and maybe someone with the same OS could assist you further.

Regards Mark
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.