dwk*_*kns 9 javascript applescript automation osx-yosemite javascript-automation
我正在尝试将一些旧的Applescript移植到新的JavaScript语法中.
事情似乎非常直接,所以:
tell application "System Events" to keystroke "t" using command down
Run Code Online (Sandbox Code Playgroud)
成为:
System = Application('System Events');
System.keystroke("t", {using: "command down"})
Run Code Online (Sandbox Code Playgroud)
但是我不能为我的生活找出如何列出特定位置的文件.在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"}
Run Code Online (Sandbox Code Playgroud)
但是我不能为我的生活弄清楚如何在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)
-- > []
Run Code Online (Sandbox Code Playgroud)
我也尝试了很多其他组合,但没有运气.有任何想法吗?
foo*_*foo 13
就像Leopard的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()
Run Code Online (Sandbox Code Playgroud)
AS版本运行完美,但JXA等效只是抛出一个完全没有意义的东西 Error -1700: Can't convert types.
如果你写diskItems
而不是JXA似乎工作items
:
Application('System Events').folders.byName('/usr').diskItems.name()
// --> ["bin", "lib", "libexec", "local", "sbin", "share", "standalone", "X11", "X11R6"]
Run Code Online (Sandbox Code Playgroud)
这表明JXA沉迷于同样的内部"聪明",导致SB打破这么多的应用程序.(请注意,我在早期的测试中发现了许多这样的设计缺陷,但是一旦明确了AS开发人员只关心强加他们自己的个人意识形态和对其他人的偏见,残缺的能力和破坏的兼容性被诅咒就放弃了.)
为了比较,这里是JavaScriptOSA(JOSA)原型我几个月前很快就为JXA开发人员的参考组合在一起(他们很快忽略了它,natch):
app('System Events').folders.named('/usr').items.name()
// -> ["bin", "lib", "libexec", "local", "sbin", "share", "standalone", "X11", "X11R6"]
Run Code Online (Sandbox Code Playgroud)
(虽然没有完全完成或测试,但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"]
Run Code Online (Sandbox Code Playgroud)
您可以通过将Path对象转换为字符串并使用它来解决该特定情况:
myPath = Path('/usr')
Application('System Events').folders.byName(myPath.toString()).diskItems.name()
Run Code Online (Sandbox Code Playgroud)
虽然这种解决方法在其他情况下不一定有用; 例如,它在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.
Run Code Online (Sandbox Code Playgroud)
它就这样了.(例如,尝试测试JXA对范围,过滤器,相对和插入参考形式的支持 ;它特别腐烂.)
这种"System Events"
方法确实具有简单性的优点,但事实证明使用$.NSFileManager
(现在可直接用于脚本)可以显着提高性能.
在我的系统上,开始与之比较
var strPath = '/usr';
var appSys = Application('System Events'),
lstHarvest = appSys.folders.byName(strPath).diskItems.name();
Run Code Online (Sandbox Code Playgroud)
几千次迭代的快速测试表明,通过这种略微巴洛克式的方法,我们可以通过适度的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)
);
});
Run Code Online (Sandbox Code Playgroud)
而且相当简单,超过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)
);
});
Run Code Online (Sandbox Code Playgroud)