我正在尝试将一些旧的Applescript移植到新的JavaScript语法中。
有些事情似乎很直接,所以:
tell application "System Events" to keystroke "t" using command down
成为:
System = Application('System Events');
System.keystroke("t", {using: "command down"})
然而,我不能为我的生活找出如何列出特定位置的文件。在AppleScript中,要返回/usr
目录中的文件列表,您可以执行以下操作:
tell application "System Events" to set fileList to name of items in folder "/usr"
-- > {"bin", "include", "lib", "libexec", "local", "sbin", "share", "standalone", "X11"}
然而,我不能为我的生活找出如何在Javascript中做到这一点。
System = Application('System Events')
myPath = Path("/usr")
fileList = System.items(myPath)
-- > message not understood
fileList = System.folder(myPath)
-- > message not understood
fileList = System.diskItems(myPath)
-- > []
fileList = System.diskItems({at:myPath)
-- > []
我也尝试了很多其他组合,但没有运气。有什么想法吗?
答案 0 :(得分:13)
就像之前的Leopard's Scripting Bridge一样,JXA故意打破在AppleScript中完美运行的各种东西。以下是原始AppleScript命令到JXA语法的转换:
//tell application "System Events" to name of items in folder "/usr"
Application('System Events').folders.byName('/usr').items.name()
AS版本运行完美,但JXA等效只是抛出一个完全没有意义的Error -1700: Can't convert types.
如果您编写diskItems
而不是items
,JXA似乎有效:
Application('System Events').folders.byName('/usr').diskItems.name()
// --> ["bin", "lib", "libexec", "local", "sbin", "share", "standalone", "X11", "X11R6"]
这表明JXA沉溺于同样的内部"聪明"导致SB打破这么多应用程序。 (请注意,我在早期的测试中发现了许多这样的设计缺陷,但是一旦明确了AS开发人员只关心强加他们自己的个人意识形态和对其他人的偏见,残缺的能力和破坏的兼容性被诅咒就放弃了。)
为了进行比较,这里是JavaScriptOSA (JOSA) prototype我为JXA开发人员快速组建的reference forms'几个月前参考(他们很快忽略了它,自然):
app('System Events').folders.named('/usr').items.name()
// -> ["bin", "lib", "libexec", "local", "sbin", "share", "standalone", "X11", "X11R6"]
(虽然没有完全完成或测试,但JOSA仍然比JXA更好看,更好地记录,甚至还包括一个自动翻译工具,用于将AS命令转换为JS语法。不幸的是,因为Apple有遗产或弃用AEM,CM,PM和OSA Carbon API,我不推荐它用于生产用途;它纯粹用于比较目的。)
类似地:
set myPath to POSIX file "/usr"
tell application "System Events" to name of every disk item of folder named myPath
--> {"bin", "lib", "libexec", "local", "sbin", "share", "standalone", "X11", "X11R6"}
myPath = Path('/usr')
Application('System Events').folders.byName(myPath).diskItems.name()
// Error -1728: Can't get object.
var myPath = Path('/usr')
app('System Events').folders.named(myPath).diskItems.name()
// --> ["bin", "lib", "libexec", "local", "sbin", "share", "standalone", "X11", "X11R6"]
您可以通过将Path对象转换为字符串并使用它来解决该特定情况:
myPath = Path('/usr')
Application('System Events').folders.byName(myPath.toString()).diskItems.name()
虽然这种解决方法在其他情况下不一定有帮助;例如它在Finder中失败,因为Finder不了解POSIX风格的路径字符串,并且无法从JXA Path对象获取HFS样式的路径字符串(Finder确实理解):
set myPath to POSIX file "/usr"
tell application "Finder" to name of every item of item myPath
--> {"X11", "X11R6", "bin", "lib", "libexec", "local", "sbin", "share", "standalone"}
myPath = Path('/usr')
Application('Finder').folders.byName(myPath.toString()).items.name()
// Error -1728: Can't get object.
就这样吧。 (例如,尝试测试JXA对范围,过滤器,相对和插入{{3}}的支持;它特别糟糕。)
答案 1 :(得分:7)
"System Events"
方法确实具有简单性的优点,但事实证明使用$.NSFileManager
(现在可直接用于脚本编写)可以显着提高性能。
在我的系统上,开始与
进行比较var strPath = '/usr';
var appSys = Application('System Events'),
lstHarvest = appSys.folders.byName(strPath).diskItems.name();
经过几千次迭代的快速测试表明,采用这种略微巴洛克式的方法,我们可以通过适度的40%来加速它:
var strPath = '/usr';
var fm = $.NSFileManager.defaultManager,
oURL = $.NSURL.fileURLWithPathIsDirectory(strPath, true),
lstFiles = ObjC.unwrap(
fm.contentsOfDirectoryAtURLIncludingPropertiesForKeysOptionsError(
oURL, [], 1 << 2, null
)
),
lstHarvest = [];
lstFiles.forEach(function (oItem) {
lstHarvest.push(
ObjC.unwrap(oItem.path)
);
});
并且通过相当简单的超过300%:
var strPath = '/usr';
var fm = $.NSFileManager.defaultManager,
lstFiles = ObjC.unwrap(
fm.contentsOfDirectoryAtPathError(strPath, null)
),
lstHarvest = [];
lstFiles.forEach(function (oItem) {
lstHarvest.push(
ObjC.unwrap(oItem)
);
});
答案 2 :(得分:2)
我可以像这样得到它
foldersList = foldersList = System.folders.byName("usr").folders.name()
- &GT; [“bin”,“lib”,“libexec”,“sbin”,“share”,“standalone”,“X11”]
即便如此:
foldersList = System.folders.byName("/Users/USERName/Documents/").folders.name()
但到目前为止,我无法使用Path命令处理除“打开”之外的任何事情