10

古い 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)
-- > []

他の組み合わせもたくさん試しましたが、うまくいきません。何か案は?

4

3 に答える 3

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()

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"]

これは、JXA が、SB が非常に多くのアプリで壊れる原因となっているのとほぼ同じ内部の「賢さ」にふけることを示唆しています。(私は以前のテストでそのような設計上の欠陥を多数発見しましたが、AS 開発者が自分の個人的なイデオロギーと偏見を他のすべての人に押し付けることだけを気にかけていることが明らかになると、それらを報告することを断念したことに注意してください。不自由な機能と壊れた互換性はひどいものです。)

比較のために、私が数か月前に JXA 開発者の参照用に簡単にまとめたJavaScriptOSA (JOSA) プロトタイプを次に示します (彼らはすぐにそれを無視しました、ナッチ)。

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 のサポートをテストしてみてください。特に腐っています。)

于 2014-10-11T17:10:40.660 に答える
8

"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)
    );
});
于 2015-02-05T21:00:39.450 に答える