2

我正在尝试制作一个苹果脚本,用于将大量照片导入 Aperture,因为 Aperture 在这种情况下经常崩溃。出于这个原因,我想将每个文件分别导入到库中。我最初的尝试适用于一张图片:

on run argv
set file_name to item 1 of argv


tell application "Aperture"
activate
    tell library 1
      if not (exists project "OldPictures") then
          set theProject to make new project with properties {name:"OldPictures"}
      else
          set theProject to project "OldPictures"
      end if
end tell
with timeout of 600 seconds
      import file_name by moving into theProject
end timeout
end tell

end run

但是如果我按以下方式运行它会崩溃

find /Volumes/Pictures/ -iname "*.jpg" -exec  osascript /Users/mac/apperture.scpt  {} \;
4

1 回答 1

0

蛮力肌肉导入

你可能想试试这个硬核脚本。它需要 AGES 才能完成,但它应该可以工作,因为它会按照您的要求执行……它将每个文件一个接一个地添加到指定的项目中,并检查以确保没有任何仅按名称重复的文件。我即将在 13262 张图片上测试这个脚本。它可能会运行一整夜,但它有望击败不断失败的内置导入器。

我建议您在第一次运行时创建一个测试项目,以确保您不会导入重复项。然后,您可以选择将图像移动到 Aperture 中的相应项目中。我已经设置好了。如果您想忽略这一点并将它们直接导入到原始项目中,您可以通过更改以下行来做到这一点:

  • my importToApertureAsReference(itemAlias, projectDst)

  • my importToApertureAsReference(itemAlias, projectName)

OS X 10.9.4

光圈3.5.1

免责声明:我只是把它放在一起。有改进的余地,比如检查以确保列表中的文件都是图片。我没有做任何这样的检查。这可以在 shell 命令中完成,或者使用系统事件来获取每个文件通过时的类型。此外,当您运行此程序时,您的计算机将翻转。我建议你不要在你的电脑上做任何其他事情。

AppleScript - 将缺失的文件一一导入项目”

通过比较图片的名称和文件的名称

2014 年 8 月 1 日更新

通过让 bourne 脚本完成大部分工作,我显着提高了脚本的速度。AppleScript 在与程序交谈时会陷入困境,但在迭代列表时相对较快。我只是使用了 bourne 脚本的find命令basename来创建一个没有路径的所有文件的新列表。AppleScript 迭代此列表并将其与您指定项目中的名称列表进行比较。如果它发现项目中不存在的文件projectName则将projectDst文件名的路径连接起来,并将其作为参考添加到项目目标中。如果您想将文件复制到库中而不仅仅是作为参考,则需要调整处理程序importToApertureAsReference或创建一个名为importToApertureAsCopyingor的新处理程序importToApertureAsMoving

set inputPath to "Volumes:Kielbasa:Camera:1970 - Fotos" as string
set inputPathHFS to inputPath as alias
log "inputPathHFS: " & inputPathHFS
set projectName to "1970 - Fotos" -- Check this project for duplicates
set projectDst to "AppleScript Import" -- This is where any missing files will be added
set importedList to {}

set inputPathPX to text 1 through -2 of POSIX path of inputPathHFS
log "inputPathPX: " & inputPathPX
set countItemsCommand to "find " & quoted form of inputPathPX & " -type f -maxdepth 1 \\! -name '.*' | wc -l"
set getItemsCommand to "find " & quoted form of inputPathPX & " -type f -maxdepth 1 ! -name '.*' -exec sh -c 'basename \"{}\"' \\;"

set itemCount to (do shell script countItemsCommand) as integer
set itemList to paragraphs of (do shell script getItemsCommand) as list
set missingItemsList to {}

set namesInProjectList to my getAllNamesInProject(projectName) as list

-- Check whether your project contains an object/item (image/video) with the same name
repeat with itemStep from 1 to count of itemList
    set thisItem to item itemStep of itemList
    log "This Item: " & thisItem
    set itemSplit to my splitExtension(thisItem)
    set itemName to item 1 of my splitExtension(thisItem)
    set itemExt to item 2 of my splitExtension(thisItem)
    log "Item Name: " & itemName & ", Item Ext: " & itemExt
    log "Checking if project " & projectName & " contains " & itemName
    set foundImages to my findAll(namesInProjectList, itemName)
    if foundImages is {} then -- if empty, then there is no match so image should be added to Aperture
        set end of missingItemsList to contents of thisItem -- this makes a new list of all missing images with extensions (no path), to import into Aperture you need to join this item with its full path

        set picAlias to (inputPathHFS as string) & thisItem as alias
        log "Importing: " & picAlias
        my importToApertureAsReference(picAlias, projectDst)
    else
        repeat with foundIndex in foundImages
            my deleteItem(namesInProjectList, foundIndex)
            log "Found Index: " & foundIndex
            log "Removed from namesInProjectList: " & thisItem
        end repeat
    end if
end repeat


return missingItemsList

(*
tell application "System Events"
    repeat with itemStep from 1 to count of itemList
        set thisItem to item itemStep of itemList
        log "This Item: " & thisItem
        set itemSplit to my splitExtension(thisItem)
        set {itemName, itemExt} to {item 1 of itemSplit, item 2 of itemSplit}
        log "Item Name: " & itemName & ", Item Ext: " & itemExt
        log "Checking if project " & projectName & " contains " & itemName
        -- Compare Lists
        if namesInProjectList does not contain itemName then
            if otherList does not contain itemName then
                -- Generate Alias from filename by joining inputpath and filename
                set thisFileAlias to inputPath & ":" & thisItem as alias -- eg "Volumes:Kielbasa:Camera:1970 - Fotos000_0014.jpg"
                my importToApertureAsReference(thisFileAlias, projectDst)
                log "Imported: " & thisFileAlias
                set end of importedList to thisFileAlias
            end if
        end if

    end repeat
end tell
*)
return importedList

on importToApertureAsReference(picAlias, projectName)
    log "Importing: " & picAlias
    tell application "Aperture"
        tell library 1
            if not (exists project projectName) then
                set projectDst to make new project with properties {name:projectName}
            else
                set projectDst to project projectName
            end if
            import picAlias by referencing into projectDst
        end tell
    end tell
end importToApertureAsReference


on getAllNamesInProject(projectName)
    tell application "Aperture"
        tell library 1
            tell project projectName
                set nameList to name of image versions
            end tell
        end tell
    end tell
    return nameList
end getAllNamesInProject


on splitExtension(file_name)
    set dot to "."
    tell AppleScript
        set oT to text item delimiters
        set text item delimiters to dot
        if (count text items of file_name) > 1 then
            set out_name to (text items 1 through -2 of file_name) as string
            set ext to last text item of file_name
        else
            set out_name to file_name
            set ext to ""
        end if
        set text item delimiters to oT
        if ext is not "" then set ext to dot & ext
        return {out_name, ext}
    end tell
end splitExtension

on deleteItem(lst, idx)
    local lst, idx, len, ndx, l
    try
        if lst's class is not list then error "not a list." number -1704
        script k
            property l : lst
        end script
        set len to count of k's l
        set ndx to idx as integer
        if ndx is 0 then
            error "index 0 is out of range." number -1728
        else if ndx < 0 then
            set ndx to len + 1 + ndx
            if ndx < 1 then error "index " & idx & ¬
                " is out of range." number -1728
        else if ndx > len then
            error "index " & idx & " is out of range." number -1728
        end if
        if ndx is 1 then
            return rest of k's l
        else if ndx is len then
            return k's l's items 1 thru -2
        else
            return (k's l's items 1 thru (ndx - 1)) & ¬
                (k's l's items (ndx + 1) thru -1)
        end if
    on error eMsg number eNum
        error "Can't deleteItem: " & eMsg number eNum
    end try
end deleteItem

on findAll(lst, val)
    local lst, val, res
    try
        if lst's class is not list then error "not a list." number -1704
        if {val} is not in lst then return {}
        set res to {}
        script k
            property l : lst
        end script
        repeat with i from 1 to count of k's l
            if k's l's item i is val then set res's end to i
        end repeat
        return res
    on error eMsg number eNum
        error "Can't findAll: " & eMsg number eNum
    end try
end findAll

Python - 将缺少的文件一一导入项目(使用 AppleScript)

AppleScript 因 13262 张图片的负载而窒息。当 AppleScript 变大时,这些列表对它们来说太多了,所以我决定编写一个 Python 脚本。使用 Python,我可以将两个集合(作为集合的列表)相减,从而创建一个仅包含缺失项的新列表。这消除了再次检查列表中的每个项目的需要另一个列表中的每个项目。它显着加快了该过程。

#!/usr/bin/env python
# -*- coding: utf-8 -*- 
# Imports
import subprocess
from subprocess import Popen, PIPE
import unicodedata
import codecs
import os


inputPath = "/Volumes/Kielbasa/Camera/1970 - Fotos" ## This is the source folder containing all images and videos you want to ensure are in your project (projectOriginal)
projectOriginal = "1970 - Fotos" ## This is where photos from original input are (if you just want to import everything from harddrive one by one, then create an empty project and use it here)
projectDst = "Python Import" ## This is where you will import all of the images and videos that are missing from you project. It is a debugging project (so that you don't screw anything up). You can then drag the images over to the projectOriginal project after ensuring that everything worked correctly.

importedList = []

getItemsCommand = """find '%s' -type f -maxdepth 1 ! -name '.*' -exec sh -c 'basename "{}"' \;""" % inputPath

#subprocess.check_output(*popenargs, **kwargs)
## itemsListEXT is a list of all files in your HD folder with extensions (Aperture projects import filenames without extensions, which I henceforth refer to as names). This list will be used to reconstruct the file paths later. It is important to have this if you have files with different extensions (e.g. images and movies, jpg, jpeg, png, raw)
itemsListEXT = subprocess.check_output(getItemsCommand, shell=True, executable="/bin/bash").splitlines()
itemCount = len(itemsListEXT)

def getItemsInProject(projectOriginal):
    cmd = """osascript<<END
    tell application "Aperture"
            tell library 1
                tell project "%s"
                    return name of image versions
                end tell
            end tell
        end tell
    END""" % projectOriginal
    itemsListEXT = subprocess.check_output(cmd,shell=True,executable="/bin/bash").split(', ')
    return itemsListEXT

## namesInProjectList is a list containing all names of images inside your projectOriginal project.
namesInProjectList = getItemsInProject(projectOriginal)

## namesOnHDList is a list that will be populated with all of the items in itemsListEXT, but without the extensions. The indexes must be the same between these two lists for reconstructing the file paths later.
namesOnHDList = []

for itemStep,thisItem in enumerate(itemsListEXT):
    #print itemStep, thisItem.decode('UTF-8')
    name,ext = os.path.splitext(thisItem)
    namesOnHDList.append(name)

missingItemsList = []
for itemStep,thisItem in enumerate(namesOnHDList):
    if thisItem in namesInProjectList:
        ## Just a place holder
        continue
    else:
        ## This reconstructs full paths out of all the missing item names by getting name + extension from itemsListEXT (the indexes in these two lists MUST be the same)
        missingItemsList.append(os.path.join(inputPath,itemsListEXT[itemStep]))

## This is for debugging only. You can compare the total number of missing items to the difference between your project and HD items. If that number is the same as the sum of items in missingItemsList, then it is likely working.
print len(missingItemsList)
print missingItemsList


def importToApertureAsReference(objectPath,projectDestination):
    scpt = '''
    on run {objectPath,projectDestination}
        set objectAlias to POSIX file objectPath as alias
        set projectName to projectDestination
        tell application "Aperture"
            tell library 1
                if not (exists project projectName) then
                    set projectDst to make new project with properties {name:projectName}
                else
                    set projectDst to project projectName
                end if
                import objectAlias by referencing into projectDst
            end tell
        end tell
    end run
    '''
    args = [objectPath, projectDestination]
    p = Popen(['osascript', '-'] + args, stdin=PIPE, stdout=PIPE, stderr=PIPE)
    stdout, stderr = p.communicate(scpt)
    print (p.returncode, stdout, stderr)
    print "--> Imported: " + objectPath +  " to Project: " +  projectDestination

## Add all items from the missingItemsList to your Aperture project destination (projectDst)
countItems = len(missingItemsList)
for itemStep,thisItem in enumerate(missingItemsList):
    importToApertureAsReference(thisItem,projectDst)
    print "Item: " + str(itemStep) + " of " + str(countItems)

最初发布的 AppleScript

set inputPath to "Volumes:Kielbasa:Camera:1970 - Fotos" as alias
log "inputPath: " & inputPath
set projectName to "1970 - Fotos" -- Check this project for duplicates
set projectDst to "AppleScript Import" -- This is where any missing files will be added
set importedList to {}

set inputPathPX to text 1 through -2 of POSIX path of inputPath
log "inputPathPX: " & inputPathPX
set countItemsCommand to "find " & quoted form of inputPathPX & " -type f \\! -name '.*' | wc -l"
set getItemsCommand to "find " & quoted form of inputPathPX & " -type f ! -name '.*'"

set itemCount to (do shell script countItemsCommand) as integer
set itemList to paragraphs of (do shell script getItemsCommand) as list


set namesList to my getAllNamesInProject(projectName) as list
set otherList to my getAllNamesInProject("Test Project") as list


tell application "System Events"
    repeat with itemStep from 1 to count of itemList
        tell me to set itemAlias to POSIX file (item itemStep of itemList) as alias
        log itemAlias
        set itemName to name of itemAlias
        set fileNameNOEXT to item 1 of my splitExtension(itemName)
        log "Checking if project " & projectName & " contains " & fileNameNOEXT
        if namesList does not contain fileNameNOEXT then
            if otherList does not contain fileNameNOEXT then
                my importToApertureAsReference(itemAlias, projectDst)
                set end of importedList to itemAlias
            end if
        end if
    end repeat
end tell

return importedList

on importToApertureAsReference(picAlias, projectName)
    log "Importing: " & picAlias
    tell application "Aperture"
        tell library 1
            if not (exists project projectName) then
                set projectDst to make new project with properties {name:projectName}
            else
                set projectDst to project projectName
            end if
            import picAlias by referencing into projectDst
        end tell
    end tell
end importToApertureAsReference


on getAllNamesInProject(projectName)
    tell application "Aperture"
        tell library 1
            tell project projectName
                set nameList to name of image versions
            end tell
        end tell
    end tell
    return nameList
end getAllNamesInProject


on splitExtension(file_name)
    set dot to "."
    tell AppleScript
        set oT to text item delimiters
        set text item delimiters to dot
        if (count text items of file_name) > 1 then
            set out_name to (text items 1 through -2 of file_name) as string
            set ext to last text item of file_name
        else
            set out_name to file_name
            set ext to ""
        end if
        set text item delimiters to oT
        if ext is not "" then set ext to dot & ext
        return {out_name, ext}
    end tell
end splitExtension

提示:如果您单击 AppleScript 编辑器底部的事件或响应选项,您可以查看正在发生的事情(最好在运行脚本之前执行此操作)

于 2014-07-30T17:06:31.103 回答