'Creating a file object from an HFS string

I'm learning AppleScript from various online articles and yt tutorials and I've come a cropper over the whole Files and Alias topic.

According to this guide, (listing 15.8) I should be able to create a file object with the line

set theFile to file "Macintosh HD:Users:yourUserName:Desktop:My File.txt"

This throws up an error

Script Editor error

I've done a lot of googling and only found one reference to the issue:

Oddly, you can't assign a file object specifier to a variable, or return it as a value. If you try, you get a runtime error message:

set x to file "feathers:Users:mattneub:"
-- error: Can't make file "feathers:Users:mattneub:" into type reference

Instead, you must generate a reference to the file object, like this:

set x to a reference to file "feathers:Users:mattneub:"
x -- file "feathers:Users:mattneub:" of «script»

In the AppleScript Language Guide a file object is created via the pseudo class POSIX file

Working With Files
AppleScript uses file objects to represent files in scripts. A file object can be stored in a variable and used throughout a script. The following script first creates a file object for an existing file in the variable notesFile, then uses the variable in a tell statement that opens the file:

set notesFile to POSIX file "/Users/myUser/Feb_Meeting_Notes.rtf"
tell application "TextEdit" to open notesFile

I find this bizarre!

As I understand it, file paths inside the file object are stored as HFS, so should I want to create a file object from an HFS string, I need to

  • create a POSIX path from the HFS string
  • put the POSIX path through POSIX file

which returns a file object with the path stored as an HFS string again!

(Although apparently POSIX file doesn't even output a file object, but a file URL?!)

My question in short: Why can't I set a variable as a file object by appending file to an HFS string as in the listing 15.8 quoted above? Do I always have to go via POSIX path and POSIX file?.

I'm wondering if the code does actually work, just not on its own? I haven't actually got as far as to work out why I need or how to use file objects, so my understanding could be patchy...

In a tutorial about converting between POSIX and HFS paths, and aliases, I decided to try and convert an alias to a file object and opened this can of worms.

Any help is much appreciated, even if the answer is: you'd never need to do this, so just ignore it! 😅



Solution 1:[1]

Here you do not understand what the manuals explain. Listing 15.8 shows exactly the wrong attempt to create a file reference using old type file specifier (file). This specifier is left over from the past to work with AppleScript commands such as read and write.

The manual clearly shows the correct creation of the old type file reference (file) from HFS path:

set theFile to a reference to file "Macintosh HD:Users:yourUserName:Desktop:My File.txt"

Later, you can use this reference any time with AppleScript commands read and write. For example:

read theFile

Also, the manual clearly states that it is additionally possible to use the read or write command without first creating a separate file reference (variable theFile in your case). So to speak, to read or write "on the fly":

read file "Macintosh HD:Users:yourUserName:Desktop:My File.txt"

Solution 2:[2]

Short version: AppleScript is an absolute dumpster file.

Longer version: AppleScript overloads object specifiers to perform 2 very different tasks:

  1. assemble complex queries identifying data in apps, e.g. (in Finder) file "bar" of folder "Downloads" of home,

  2. create new instances of primitive AppleScript types, e.g. alias "Macintosh HD:Users:foo:Downloads:bar:".

Pre OS X, the file STRING specifier was syntactic shorthand for file specification STRING, which created a new instance of AS’s file specification type (#2). That type was deprecated and removed in OS X due to its technical limitations, but for whatever reason the file STRING specifier that constructed it was left in-place and bodged so that at least some apps will accept the resulting query (#1) as alternative to a primitive file type (alias, POSIX file).

Thus if you now write [tell APPLICATION to] open file STRING, that syntax [usually] works because AS passes the file STRING query as-is to the app’s open command to process. Whereas if you write set f to file STRING, that fails because AS no longer knows how to resolve a file STRING [of AppleScript] query for itself.

Again, it’s all horrendously confusing, and the whole mess could’ve been entirely avoided had the Mac Automation team implemented POSIX file properly and migrated everyone off those unreliable HFS paths 15 years ago in AppleScript 2.0. But if the road to Hell is paved with good intentions then AppleScript syntax is the roadkill strewn all along it.

As a rule of thumb, if you can use the POSIX file type and avoid the legacy HFS mess entirely, you will save yourself a lot of pain all round:

set f to "/Users/foo/Downloads/bar/" as POSIX file -- convert string to file type

set p to POSIX path of f -- convert file to string type

Note the use of a coercion (STRING as POSIX file) rather than an object specifier (POSIX file STRING); the coercion is the less troublesome of the two.

And yes, POSIX file doesn’t work properly, and some especially ancient Mac apps still insist on HFS paths/types even though HFS has been deprecated for 15+ years. But AppleScript’s at the end of its lifecycle and the Mac Automation team responsible for it long disbanded, so you just have to make the best out of the crap you’ve got while you’ve still got it.

TL;DR: You can see why I put the short version at the top.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 foo