0

For a specific example, here’s how to change the name of a specific file via the Finder, in AppleScript:

tell application "Finder" to set name of (POSIX file "/some/file/path" as alias) to "new name"

And here’s how to change the name of the selected file via the Finder, in JavaScript for Automation (JXA):

Application("Finder").selection()[0].name = "new name"

How can one do the last line, but acting on a specific given path rather than being limited to the selection? It’s important to use the Finder, because it allows (via the same mechanism) to do more than change the name (like set a comment).

4 Answers 4

1

It's quite odd that Finder would expose no method of converting a Path to a Finder file object, yet one doesn't appear to exist. Instead, it seems (per this question) that System Events' aliases property is the only way to convert a path string to a Finder object, like so:

file = Application('System Events').aliases['/some/file/path']
console.log(file.name()) // --> 'path'
file.name = 'newname'

Finder does allow you to manually drill down through the file hierarchy (see this answer), but it's a pain:

file = Application('Finder').startupDisk.folders['some'].folders['file'].documentFiles['path']
console.log(file.name()) // --> 'path'
file.name = 'newname'

However, only some of the attributes these objects are supposed to expose are actually working for me on Big Sur. (Reading and writing comments, for instance, does not seem to work.) If you need reliable and robust Finder scripting, JXA simply may not be the way to go.

1
  • So there is no way to go from a System Events alias to a Finder object (like a Folder or Document File)? Commented Jul 27, 2023 at 16:08
1

You can use the following function:

const F = Application("Finder")

function itemFromPosixPath(path) {
    let item = F.startupDisk;
    // path: "/Users/me/Desktop/"
    // path.split("/"): ["", "Users", "me", "Desktop", ""]
    // components: ["Users", "me", "Desktop"]
    // POSIX paths on Mac swap slashes and colons in filenames
    const components = path.split("/").filter(name => name).map(name => name.replace(/:/g, "/"));
    // traverse, building the query
    for (const component of components) {
        item = item.items.byName(component);
    }
    // execute the query
    return item()
}
0
0

This will do it in a functional way and work on external volumes.

function asFinderItem(posixPath) {
  return posixPath
    .split("/") // Split into path components
    .slice(1)   // Delete the first (empty) part
    .map(component => component.replace(/:/g, "/")) // Correct component names
    .reduce(    // Merge everything
      (accumulator, entry) => accumulator.items.byName(entry),
      Application("Finder").startupDisk()
    )
}

Example usage:

asFinderItem("/some/file/path").name = "new name"
-1

There is a global Path mentioned in the docs

This works for me:

Application("Finder").delete(Path("/a/b/c"));

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .