MacOS Photos - 使用 applescript 使用它们所在相册的名称更新关键字
MacOS Photos - use applescript to update keywords with the name(s) of the albums they are in
TLDR:
我想要 运行 一个 Applescript,它将迭代智能相册中新添加的照片,以将它们包含的相册名称和文件夹名称添加为照片上的关键字。
案例:
我的照片结构是这样的:
My Albums¬
FolderName¬
AlbumName¬
List of Photos
我创建了一个智能相册:“过去 90 天内添加的任何照片”
我希望 applescript 基本上做到这一点:
- Select 智能相册中的照片
- 遍历每一个,“询问”它们在哪些相册和文件夹中
- 复制相册名称和文件夹名称以将它们附加到照片的 'keywords'。
我所知道的关于照片应用程序工作方式的一些事情:
- 照片不知道它们在哪个相册中
- 相册知道它们包含哪些照片
- Applescript 字典读取容器的方式很不稳定。
- 经过研究,我认为诀窍是 'ask' 相册中有所选照片的所有文件夹,然后以某种方式捕获相册名称和 'contains photo' 所在的文件夹。但是我真的不知道怎么做这个
这 3 件事让我很困惑。
我真的很希望有人做过这样的事情,可以帮助我理解围绕这个的脚本。
最终,我尝试使用智能过滤器使照片更易于搜索 - 因此自动附加关键字会有很大帮助。
到目前为止,我可以让 applescript 找到要迭代的选择(手动选择的文件),但我真的很想通过命名的智能相册完成它。
tell application "Photos"
set eachFile to {}
set theSelections to (get selection) -- This gets the hilighted photos
repeat with i in theSelections
set selectedPhotoId to get id of i
set theKeywords to the ({keywords of i})
display dialog theAlbum
end repeat
end tell
到目前为止,我的努力只是弄清楚哪些字典术语可以 return 对我有一些价值,但到目前为止我遗漏了很多部分。
循环遍历特定相册中的所有照片很容易,主要要求它是顶级相册。 (你可以在子专辑中做到这一点,但这会变得不那么容易。)
set sourceAlbumName to "Last Fortnight"
repeat with recentPhoto in media items in album sourceAlbumName
…
end repeat
剩下的就更难了,因为你提到的原因:据我所知,你不能只要求包含照片的所有相册的列表。
但是,您可以询问文件夹 它 是否包含包含该照片的任何相册。
所以您最终需要做的是遍历所有文件夹(包括顶级文件夹,应用程序本身)并找到包含照片的所有相册。将他们的名字添加到关键字列表中。如果文件夹中有文件夹,则同理
然后,为了您的目的,如果任何文件夹包含包含该照片的相册,或包含包含包含该照片的相册的文件夹等,请将该文件夹也添加到关键字列表中。
这几乎需要递归处理程序。
这个示例处理程序所做的是,它首先获取指定文件夹中的所有相册,并将它们复制到新关键字列表中。然后它遍历指定文件夹中的每个文件夹,并使用该文件夹调用处理程序。如果它得到了一些东西,那么它将把它得到的东西和文件夹添加到新关键字列表中。
to getSubcontainers for parentFolder given id:photoId
set newKeywords to {}
--using terms from because tell application "Photos" has trouble
--when the parentFolder *is* application "Photos"
using terms from application "Photos"
tell parentFolder
--get the albums that contain this photo
set containingAlbums to get (albums whose id of media items contains photoId)
repeat with containingAlbum in containingAlbums
copy name of containingAlbum to end of newKeywords
end repeat
--get folders that contain albums that contain this photo
repeat with currentFolder in folders
tell me to getSubcontainers for currentFolder given id:photoId
--if some album contained within this folder contained the photo
--then this folder is also a keyword
if the result is not {} then
set newKeywords to newKeywords & the result
copy name of currentFolder as string to end of newKeywords
end if
end repeat
end tell
end using terms from
return newKeywords
end getSubcontainers
这是脚本的顶层。请注意,默认情况下它设置为在完成一张照片后停止,并且不会实际更改关键字。
我将测试相册命名为 Last Fortnight
,因为我在测试时不希望其中包含 90 天的照片。
脚本确保不会多次添加关键字,也不会将源专辑添加为关键字,因为它可能不算数。
--how many photos should we change before we bail?
set maxPhotos to 1
--if testing is true, do not actually change the keywords
set testing to true
--the album to pull photos from for changing
set sourceAlbumName to "Last Fortnight"
tell application "Photos"
set currentPhotoCount to 0
repeat with recentPhoto in media items in album sourceAlbumName
set currentPhotoCount to currentPhotoCount + 1
tell me to getSubcontainers for application "Photos" given id:id of recentPhoto
set containerNames to the result
--create a new list of keywords that includes both existing keywords on the photo
--and the new folder and album names
set photoKeys to keywords of recentPhoto
repeat with newKey in containerNames
set newKey to newKey as string
if newKey is not in photoKeys and newKey is not sourceAlbumName then
copy newKey to the end of photoKeys
end if
end repeat
--set the photo to have the new list of keywords
if not testing then
set keywords of recentPhoto to photoKeys
end if
--I'm exiting the repeat so that I can see that it worked on the first x photos in the smart album
--instead of waiting for it to go through all photos
--and also to avoid incorrectly changing too many photos
if currentPhotoCount ≥ maxPhotos then
exit repeat
end if
end repeat
end tell
--for testing, to see what the new keywords will be
if testing then
get photoKeys
end if
请注意,据我所知,没有明确的方法来判断相册是智能相册还是手动管理相册。如果这对您很重要,我怀疑尝试将照片添加到相册会 (a) 导致可捕获的错误,并且 (b) 使脚本花费更长的时间才能 运行。
如果您不想将智能相册添加为关键字,我建议您要么以某种方式标记它们的名称以便知道它们是智能的,然后排除他们就是这样 (and newKey does not end in " Smart"
),或者只是保留一个专辑列表作为关键字排除,并根据该列表检查密钥 (and newKey is not in invalidKeywords
)。我可能会选择后者。
global theKeyWords
tell application "Photos"
-- get the hilighted photos
set theSelection to (get selection)
repeat with i from 1 to count theSelection
set theKeyWords to {}
set selectionID to id of item i of theSelection
-- first, get names of albums in the root
set theKeyWords to theKeyWords & (name of albums whose id of media items contains selectionID)
-- recursively get names of albums in the subfolders
my getAlbumNames(its folders, selectionID)
-- set the keywords of processed photo
set keywords of media item id selectionID to theKeyWords
end repeat
end tell
-- recursive handler
on getAlbumNames(theFolders, selectionID)
if theFolders is {} then return
tell application "Photos"
repeat with aFolder in theFolders
tell aFolder
set theKeyWords to theKeyWords & (name of albums whose id of media items contains selectionID)
my getAlbumNames(its folders, selectionID)
end tell
end repeat
end tell
end getAlbumNames
以下脚本将关键字附加到现有关键字,而不是删除它们
global theKeyWords
tell application "Photos"
-- get the hilighted photos
set theSelection to (get selection)
repeat with i from 1 to count theSelection
set theKeyWords to {}
set selectionID to id of item i of theSelection
-- first, get names of albums in the root
set theKeyWords to theKeyWords & (name of albums whose id of media items contains selectionID)
-- recursively get names of albums in the subfolders
my getAlbumNames(its folders, selectionID)
-- set the keywords of processed photo
try
set keywords of media item id selectionID to (get keywords of media item id selectionID) & theKeyWords
on error
set keywords of media item id selectionID to theKeyWords
end try
end repeat
end tell
-- recursive handler
on getAlbumNames(theFolders, selectionID)
if theFolders is {} then return
tell application "Photos"
repeat with aFolder in theFolders
tell aFolder
set theKeyWords to theKeyWords & (name of albums whose id of media items contains selectionID)
my getAlbumNames(its folders, selectionID)
end tell
end repeat
end tell
end getAlbumNames
TLDR:
我想要 运行 一个 Applescript,它将迭代智能相册中新添加的照片,以将它们包含的相册名称和文件夹名称添加为照片上的关键字。
案例:
我的照片结构是这样的:
My Albums¬
FolderName¬
AlbumName¬
List of Photos
我创建了一个智能相册:“过去 90 天内添加的任何照片”
我希望 applescript 基本上做到这一点:
- Select 智能相册中的照片
- 遍历每一个,“询问”它们在哪些相册和文件夹中
- 复制相册名称和文件夹名称以将它们附加到照片的 'keywords'。
我所知道的关于照片应用程序工作方式的一些事情:
- 照片不知道它们在哪个相册中
- 相册知道它们包含哪些照片
- Applescript 字典读取容器的方式很不稳定。
- 经过研究,我认为诀窍是 'ask' 相册中有所选照片的所有文件夹,然后以某种方式捕获相册名称和 'contains photo' 所在的文件夹。但是我真的不知道怎么做这个
这 3 件事让我很困惑。
我真的很希望有人做过这样的事情,可以帮助我理解围绕这个的脚本。
最终,我尝试使用智能过滤器使照片更易于搜索 - 因此自动附加关键字会有很大帮助。
到目前为止,我可以让 applescript 找到要迭代的选择(手动选择的文件),但我真的很想通过命名的智能相册完成它。
tell application "Photos"
set eachFile to {}
set theSelections to (get selection) -- This gets the hilighted photos
repeat with i in theSelections
set selectedPhotoId to get id of i
set theKeywords to the ({keywords of i})
display dialog theAlbum
end repeat
end tell
到目前为止,我的努力只是弄清楚哪些字典术语可以 return 对我有一些价值,但到目前为止我遗漏了很多部分。
循环遍历特定相册中的所有照片很容易,主要要求它是顶级相册。 (你可以在子专辑中做到这一点,但这会变得不那么容易。)
set sourceAlbumName to "Last Fortnight"
repeat with recentPhoto in media items in album sourceAlbumName
…
end repeat
剩下的就更难了,因为你提到的原因:据我所知,你不能只要求包含照片的所有相册的列表。
但是,您可以询问文件夹 它 是否包含包含该照片的任何相册。
所以您最终需要做的是遍历所有文件夹(包括顶级文件夹,应用程序本身)并找到包含照片的所有相册。将他们的名字添加到关键字列表中。如果文件夹中有文件夹,则同理
然后,为了您的目的,如果任何文件夹包含包含该照片的相册,或包含包含包含该照片的相册的文件夹等,请将该文件夹也添加到关键字列表中。
这几乎需要递归处理程序。
这个示例处理程序所做的是,它首先获取指定文件夹中的所有相册,并将它们复制到新关键字列表中。然后它遍历指定文件夹中的每个文件夹,并使用该文件夹调用处理程序。如果它得到了一些东西,那么它将把它得到的东西和文件夹添加到新关键字列表中。
to getSubcontainers for parentFolder given id:photoId
set newKeywords to {}
--using terms from because tell application "Photos" has trouble
--when the parentFolder *is* application "Photos"
using terms from application "Photos"
tell parentFolder
--get the albums that contain this photo
set containingAlbums to get (albums whose id of media items contains photoId)
repeat with containingAlbum in containingAlbums
copy name of containingAlbum to end of newKeywords
end repeat
--get folders that contain albums that contain this photo
repeat with currentFolder in folders
tell me to getSubcontainers for currentFolder given id:photoId
--if some album contained within this folder contained the photo
--then this folder is also a keyword
if the result is not {} then
set newKeywords to newKeywords & the result
copy name of currentFolder as string to end of newKeywords
end if
end repeat
end tell
end using terms from
return newKeywords
end getSubcontainers
这是脚本的顶层。请注意,默认情况下它设置为在完成一张照片后停止,并且不会实际更改关键字。
我将测试相册命名为 Last Fortnight
,因为我在测试时不希望其中包含 90 天的照片。
脚本确保不会多次添加关键字,也不会将源专辑添加为关键字,因为它可能不算数。
--how many photos should we change before we bail?
set maxPhotos to 1
--if testing is true, do not actually change the keywords
set testing to true
--the album to pull photos from for changing
set sourceAlbumName to "Last Fortnight"
tell application "Photos"
set currentPhotoCount to 0
repeat with recentPhoto in media items in album sourceAlbumName
set currentPhotoCount to currentPhotoCount + 1
tell me to getSubcontainers for application "Photos" given id:id of recentPhoto
set containerNames to the result
--create a new list of keywords that includes both existing keywords on the photo
--and the new folder and album names
set photoKeys to keywords of recentPhoto
repeat with newKey in containerNames
set newKey to newKey as string
if newKey is not in photoKeys and newKey is not sourceAlbumName then
copy newKey to the end of photoKeys
end if
end repeat
--set the photo to have the new list of keywords
if not testing then
set keywords of recentPhoto to photoKeys
end if
--I'm exiting the repeat so that I can see that it worked on the first x photos in the smart album
--instead of waiting for it to go through all photos
--and also to avoid incorrectly changing too many photos
if currentPhotoCount ≥ maxPhotos then
exit repeat
end if
end repeat
end tell
--for testing, to see what the new keywords will be
if testing then
get photoKeys
end if
请注意,据我所知,没有明确的方法来判断相册是智能相册还是手动管理相册。如果这对您很重要,我怀疑尝试将照片添加到相册会 (a) 导致可捕获的错误,并且 (b) 使脚本花费更长的时间才能 运行。
如果您不想将智能相册添加为关键字,我建议您要么以某种方式标记它们的名称以便知道它们是智能的,然后排除他们就是这样 (and newKey does not end in " Smart"
),或者只是保留一个专辑列表作为关键字排除,并根据该列表检查密钥 (and newKey is not in invalidKeywords
)。我可能会选择后者。
global theKeyWords
tell application "Photos"
-- get the hilighted photos
set theSelection to (get selection)
repeat with i from 1 to count theSelection
set theKeyWords to {}
set selectionID to id of item i of theSelection
-- first, get names of albums in the root
set theKeyWords to theKeyWords & (name of albums whose id of media items contains selectionID)
-- recursively get names of albums in the subfolders
my getAlbumNames(its folders, selectionID)
-- set the keywords of processed photo
set keywords of media item id selectionID to theKeyWords
end repeat
end tell
-- recursive handler
on getAlbumNames(theFolders, selectionID)
if theFolders is {} then return
tell application "Photos"
repeat with aFolder in theFolders
tell aFolder
set theKeyWords to theKeyWords & (name of albums whose id of media items contains selectionID)
my getAlbumNames(its folders, selectionID)
end tell
end repeat
end tell
end getAlbumNames
以下脚本将关键字附加到现有关键字,而不是删除它们
global theKeyWords
tell application "Photos"
-- get the hilighted photos
set theSelection to (get selection)
repeat with i from 1 to count theSelection
set theKeyWords to {}
set selectionID to id of item i of theSelection
-- first, get names of albums in the root
set theKeyWords to theKeyWords & (name of albums whose id of media items contains selectionID)
-- recursively get names of albums in the subfolders
my getAlbumNames(its folders, selectionID)
-- set the keywords of processed photo
try
set keywords of media item id selectionID to (get keywords of media item id selectionID) & theKeyWords
on error
set keywords of media item id selectionID to theKeyWords
end try
end repeat
end tell
-- recursive handler
on getAlbumNames(theFolders, selectionID)
if theFolders is {} then return
tell application "Photos"
repeat with aFolder in theFolders
tell aFolder
set theKeyWords to theKeyWords & (name of albums whose id of media items contains selectionID)
my getAlbumNames(its folders, selectionID)
end tell
end repeat
end tell
end getAlbumNames