Yosemite에서 자동화 용 JavaScript를 사용하여 폴더에있는 모든 파일 나열


Answers

이전에 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. throw합니다 Error -1700: Can't convert types.

JXA는 items 대신 diskItems 를 작성하면 작동하는 것 같습니다.

Application('System Events').folders.byName('/usr').diskItems.name()
// --> ["bin", "lib", "libexec", "local", "sbin", "share", "standalone", "X11", "X11R6"]

이것은 JXA가 SB가 많은 앱을 망가 뜨리는 원인이되는 똑같은 내부 "영리함"에 빠져 있음을 시사한다. (내가 초기 테스트에서 수많은 디자인 결함을 발견했지만, AS devs가 다른 모든 사람들에게 자신의 개인적인 이데올로기와 편견을 두는 것에 신경 썼다는 사실이 밝혀지면이를보고하는 것을 포기했다. 기능이 손상되고 호환성이 손상되었다.)

비교를 위해 JavaScriptOSA (JOSA) 프로토 타입을 몇 달 전에 JXA 개발자의 참고서로 신속하게 작성했습니다 (즉시 natch를 무시 함).

app('System Events').folders.named('/usr').items.name()
// -> ["bin", "lib", "libexec", "local", "sbin", "share", "standalone", "X11", "X11R6"]

(완전히 완료되지 않았거나 테스트되지는 않았지만 JOSA는 여전히 JXA보다 더 잘 작동하며 문서화가 잘되어 있으며 AS 명령을 JS 구문으로 변환하기위한 자동 번역 도구도 포함되어 있습니다 .After, 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가 POSIX 스타일 경로 문자열을 인식하지 못하기 때문에 Finder에서 실패하고 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의 범위, 필터, 상대 참조 및 삽입 참조 양식에 대한 지원을 테스트 해보십시오. 특히 썩었습니다.)

Question

이전의 AppleScript를 새로운 JavaScript 구문으로 이식하려고합니다.

Somethings는 꽤 직선적 인 것처럼 보인다.

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

나는 너무 많은 다른 조합을 시도했지만 행운은 없다. 어떤 아이디어?




나는 이것을 이렇게 얻을 수있다.

 foldersList =  foldersList =  System.folders.byName("usr").folders.name()

-> [ "bin", "lib", "libexec", "sbin", "share", "standalone", "X11"]

그리고 이것조차도 작동합니다 :

   foldersList =  System.folders.byName("/Users/USERName/Documents/").folders.name()

하지만 지금까지는 Path 명령을 '열린'상태로 만들지는 못합니다.




"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)
    );
});