您的解决方案可能有效,但也许我想出的可能更可行。
在您提出的 3 个建议选项中,这些LSSharedFile*
命令确实是最好的解决方案。
随着 AppleScript 脚本包 (.scptd) 和可以保存为应用程序包 (.app) 的脚本的出现,您可以很容易地在包中包含自定义可执行文件。因此,如果您无法单独使用 AppleScript 或默认的 BSD 子系统工具来完成它,您可以利用这些可执行文件来完成您需要做的事情。
因此,在 Xcode 中,我创建了一个新的“基础工具”项目,该项目使用以下代码:
int main(int argc, const char * argv[]) {
@autoreleasepool {
UInt32 resolveFlags = 0;
NSArray *arguments = [[NSProcessInfo processInfo] arguments];
if (arguments.count > 1) {
NSArray *revisedArguments = [arguments
subarrayWithRange:NSMakeRange(1, arguments.count - 1)];
for (NSString *arg in revisedArguments) {
if ([arg isEqualToString:@"--noUserInteraction"]) {
resolveFlags |= kLSSharedFileListNoUserInteraction;
} else if ([arg isEqualToString:@"--doNotMountVolumes"]) {
resolveFlags |= kLSSharedFileListDoNotMountVolumes;
}
}
}
LSSharedFileListRef sharedFileListRef = LSSharedFileListCreate(NULL,
kLSSharedFileListRecentDocumentItems, NULL);
NSArray *sharedFileListItemRefs =
(NSArray *)LSSharedFileListCopySnapshot(sharedFileListRef, NULL);
for (id itemRef in sharedFileListItemRefs) {
NSURL *resolvedURL = nil;
LSSharedFileListItemResolve((LSSharedFileListItemRef)itemRef,
resolveFlags, (CFURLRef *)&resolvedURL, NULL);
if (resolvedURL) {
printf("%s\n", resolvedURL.path.fileSystemRepresentation);
[resolvedURL release];
}
}
if (sharedFileListRef) CFRelease(sharedFileListRef);
[sharedFileListItemRefs release];
return EXIT_SUCCESS;
}
}
虽然此代码与您的代码相似,但不必将结果写入中间文件,它只是将文件路径打印到标准输出。这应该可以大大简化 AppleScript 端的编码。构建这个 Xcode 项目的结果是一个单独的“Unix 可执行文件” recentItemsFinagler
,而不是一个应用程序包。
要在 AppleScript 中使用此构建的可执行文件,您首先需要确保将脚本保存为脚本包或应用程序,然后Bundle Contents
应启用工具栏项,如下图所示:
单击该工具栏项会显示抽屉,其中显示脚本包或应用程序包的内容。要添加您的自定义可执行文件,只需将其从 Finder 拖放,如下图所示:
这会将其复制到脚本包中,如下所示:
要在运行时定位此可执行文件,您可以使用path to resource
AppleScript 命令,它是StandardAdditions.osax
. (请注意,根据您尝试在脚本中使用该path to resource
命令的方式,当您从 AppleScript 编辑器中运行脚本而不是通过在 Finder 中双击它来运行它时,您可能会遇到“找不到资源”错误. 如果您遇到此类错误,首先确保您已保存对脚本的所有更改,然后退出 AppleScript Editor,然后在脚本后在 Finder 中双击它来启动脚本应用程序完成运行,重新打开 AppleScript 编辑器,然后重新打开脚本应用程序,然后尝试从 AppleScript 编辑器中运行,看看它是否有效)。
因此,要recentItemsFinagler
在 AppleScript 中使用它,您可以执行以下操作:
property recentItemsFinagler : missing value
if (recentItemsFinagler = missing value) then
set recentItemsFinagler to (path to resource "recentItemsFinagler")
end if
set toolPath to quoted form of POSIX path of recentItemsFinagler
set recentItemsString to (do shell script toolPath & " --noUserInteraction --doNotMountVolumes")
set recentItemsPaths to paragraphs of recentItemsString
我将逐行浏览这个 AppleScript 来解释它在做什么。我们首先创建一个全局属性recentItemsFinagler
,并将其初始值设置为missing value
。(missing value
AppleScript 相当于 Objective-C 的nil
)。
如果您不知道,AppleScript 中的全局属性就像其他语言中的全局变量一样,还有一个重要的补充:当您运行脚本并为属性赋值时,该值实际上保存在脚本文件本身中,并将持续到您下次运行脚本时。
该脚本首先检查是否recentItemsFinagler
等于missing value
,如果是,则将其设置为 的结果(path to resource "recentItemsFinagler")
,这是一个 AppleScriptalias
引用。这类似于 Finder 中的别名,因为它能够成功跟踪重命名等更改,以及从一个文件夹移动到另一个文件夹。如果我将它存储为一个简单的字符串,然后将此 AppleScript 应用程序包从我的 Documents 文件夹移动到我的桌面,则路径将不再有效,并且每次运行脚本时都必须更新该属性。
无论如何,我们然后设置recentItemsString
为 AppleScriptdo shell script
recentItemsFinagler
工具的结果,它是一个字符串。要将其转换为代表路径的字符串的 AppleScript 列表,请使用该paragraphs of
命令。
因此,通过将可执行文件包含在脚本或 AppleScript 应用程序的包中,您可以在不到 10 行代码中获得所需的结果。
示例项目:RecentItemsFiagler.zip