JXA: What's the Best Way to Get List of File Objects?

My journey with JXA continues. I think the combo of KM and JXA will be awesome.

###JXA: What’s the Best Way to Get List of File Objects?

I got the below script from JXA Cookbook, which after several other alternate scripts claims that this one is 300% faster than the native JXA code.
It works great, but results only in file names. I want a list of file objects, that I can select/set the properties of.

Any ideas?

TIA for any/all help.

/*
⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶
	JXA How to Get File List
⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶

DATE:   Mon, Nov 16, 2015
AUTHOR: JMichael / JMichaelTX (in EN & KM forums)
REF:    JXA Cookbook
	https://github.com/dtinth/JXA-Cookbook/wiki/User-Interaction-with-Files-and-Folders

Code is mostly from the JXA Cookbook, with some of my minor mods made for clarity and output.
⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶
*/


var app = Application.currentApplication()
app.includeStandardAdditions = true

var strPath = app.pathTo("home folder") + "/Documents"
// Why won't any form of "~/Documents" work?

var fm = $.NSFileManager.defaultManager,
    lstFiles = ObjC.unwrap(
        fm.contentsOfDirectoryAtPathError(strPath, null)
    ),
    lstFileNames = [];

lstFiles.forEach(function (oItem) {
    lstFileNames.push(
        ObjC.unwrap(oItem)
    );
});

console.log(lstFileNames.length)

for (i = 0, len = lstFileNames.length; i < len; i++) {
	console.log(lstFileNames[i])
}
		
var strDone = "Script Done"
strDone	// just so I don't see the "undefined" in Results panel

That example really assumes a bit of familiarity with:

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class

and I would be inclined to suggest waiting till you feel more at home with JavaScript for Automation itself before you launch into the deeper water of the ObjC classes.

Probably worth starting with an exploration of the JS equivalents of AS routes to the file system through the Finder and Standard Additions libraries:.

Thanks Rob. Perhaps so...

At this point I don't want to really develop using ObjC, but if there are snippets/functions already out there that I can use, then I would like to do so, especially when they can provide a great increase in performance.

I thought the JXA Cookbook was there to help people like me who are new to JXA. The Cookbook page I referenced quickly leads the reader down the page to the apparently "best" solution that is "300%" better than the JXA native code. Who wouldn't want faster/better?

The code is great, but perhaps an example of how/when to use it in the real world would be very helpful to newbees. Given how new JXA is, it seems to me there are a lot of newbees.

As you know, JXA examples are still very hard to come by.
Can you point me to any good examples for file management?

Thanks as always for your great insight.

The quickest route to file properties is (as in AppleScript) through the Finder:

(function () {
   var oFinder = Application("Finder");

    return oFinder.files[0].properties()	
})();

and of course you can also use the same Standard Additions file system interface as AppleScript.

(function () {

	var a = Application.currentApplication(),
		sa = (a.includeStandardAdditions = true && a);

	var oPath = a.chooseFile({
		withPrompt: "File to read",
		defaultLocation: a.pathTo("home folder") + "/Documents",
		
	});
	return oPath.toString();
})();

On ObjC, I wouldn’t personally equate faster run-time with ‘better’, or even with ‘faster’.
(Coder time is generally more expensive than machine time)

( and the release notes are pretty good on Path() objects etc)

( As for the Cookbook - you are quite right - although it introduces JXA, it also tends to assume familiarity with a number of other technologies, including ObjC and Node.js - more of a set of coder to coder notes than a tutorial for users )

1 Like

Thanks, Rob. That's very helpful. :+1:
Added to my JXA snippets. :smiley:

Rob, I just ran across a bug in this line.
The defaultLocation parameter must be an alias, so it needs the Path() function, and you have an unneeded comma.

	var oPath = a.chooseFile({
		withPrompt: "File to read",
		defaultLocation: Path(a.pathTo("home folder") + "/Documents")
		
	});

From: OS X 10.10 Release Notes

Paths

When you need to interact with files, such as a document in TextEdit, you will need a path object, not just a string with a path in it. You can use the Path constructor to instantiate paths

TextEdit = Application('TextEdit')
path = Path('/Users/username/Desktop/foo.rtf')
TextEdit.open(path)

Rob, I just ran across a bug in this line.
The defaultLocation parameter must be an alias, so it needs the Path() function, and you have an unneeded comma.

Not quite sure what you have in mind – that code runs fine here and returns a path object.

Not running on your system ?

(The trailing comma is probably better tidied up, but it's tolerated by the interpreter - lets me quickly add and remove options in that context)

PS – perhaps the source of confusion is the persistence of some AppleScript terminology in JavaScript for Automation's version of the library entries. An 'alias' is an object in the AppleScript type system – one of those types which don't map directly to anything in the JavaScript type system, but is still referred to in the library text. JavaScript knows what to do with a string at this point.

Rob, I get the following error in Yosemite 10.10.5 when I run your JXA script:

But it still a syntax error. Just because it is allowed now (incorrectly) by the interpreter does not mean it will be allowed in a future update. It should not compile.

It is also confusing for a lot of readers, especially those new to JavaScript and/or JXA.

I get the following error in Yosemite 10.10.5 when I run your JXA script:

Thanks - useful to see that. It's fixed in 10.11

But it still a syntax error.

No. That's part of the ECMAScript spec.

http://ecma262-5.com/ELS5_HTML.htm#Section_11.1.5

Perhaps you are technically correct. The spec you referenced is too hard to read, or I should say not worth my time for this issue. It was not immediately obvious.

IMO, even if it is correct, it hinders readability. I do believe most people would expect another parameter after the comma. A dangling comma just looks wrong from every perspective I have.

IMO the cons of having a dangling comma far outweigh the benefits.

IMO the cons of having a dangling comma far outweigh the benefits.

Well, I'm sure that the ECMAScript committees would be pleased to hear from you. It's part of the ES6 spec too, but you may be in time to bring your influence to bear on ES7 : - )

One context in which you do need to prune out trailing commas (in object and array literals) is in JSON strings, which are still based on on pre ES5 standards.

Right! I'm firing off an email and registered letter as I'm typing this. :astonished:

1 Like