By John Gruber
Never deploy an infrastructure bastion again. Try Tailscale now.
The Standard Additions scripting addition defines the
command; you tell it which folder you want, it returns an alias
pointing to that folder.
So, for example, you can say:
set p1 to path to application support
And it will return an alias to the “Application Support” folder in
your top-level Library folder. Aliases use HFS-style paths, so the
p1 in this case) will look something like this:
Tycho HD:Library:Application Support:
There are a couple of dozen special folder names you can pass to
so forth. Consult the Standard Additions scripting dictionary for the
Because of the layered system folder layout on Mac OS X, there are more than one instance of some of these folders. For example, with the “Application Support” folder, there’s one in the top-level “Library” folder, and there’s another one inside the “Library” folder in each user’s home folder.
These different layers are called file-system domains in Mac OS X’s
parlance.1 You can pass the
to command a
from parameter, which allows you to specify which
domain you want. As evidenced above, if you omit the
it defaults to the Local domain (i.e. the top-level “Library” folder
shared by all users).
To get the current user’s “Application Support” folder, ask for the User domain:
set p1 to path to application support from user domain
This returns something like:
Tycho HD:Users:gruber:Library:Application Support:
So, given all that, take a guess what this returns:
tell application "System Events" set p2 to path to application support from user domain end tell
The reasonable guess, of course, is that it would return the same
thing. Alas, no. Instead, in the above snippet,
p2 is set to:
Tycho HD:Library:Application Support:
I.e. by placing the
path to command within a
"System Events" block, it no longer honors the
from user domain
parameter, and instead always returns the folder from the Local
This is particularly insidious because inside a
"System Events" block is exactly where you’re likely to want to get
the path to a folder, because you can’t do much with an alias to a
folder except within such a block. AppleScript, by itself, doesn’t let
you do anything with a folder.
For example, let’s say you want to get a list of every item within the user’s “Application Support” folder. You can’t just say this:
set p to path to application support from user domain set my_list to every item of p
because you’ll get an error on the
every item of part. You need to
ask an application that knows how to do something with a folder. The
Finder can do this, but the recommended way to script this is to use
System Events instead. But you can’t just say this:
tell application "System Events" set p to path to application support from user domain set my_list to every item of p end tell
because once you move the
path to command into the System Events
tell block, you get the wrong answer. Instead, you have to remember
this, and write it like this, with the
path to statement outside the
set p to path to application support from user domain tell application "System Events" set my_list to every item of p end tell
The Finder, however, does not suffer from the same bug as System Events.2 This works as expected:
tell application "Finder" set p to path to application support from user domain set my_list to every item of p end tell
The reason to prefer System Events over Finder for this sort of thing is that, ostensibly, Finder is technically “optional” — users of third-party file managers like Path Finder might not be using the Finder. System Events, however, is always available.
This sort of bug is precisely why so many people despise AppleScript.
Not only does it make no sense, but something like this can be
maddeningly difficult to track down. Imagine if you start with the
path to statement outside the System Events tell block, and
everything is working as you expect. Then, while cleaning up the code,
you move the
path to statement into the tell block, to keep it next
to the other lines of code that pertain to the folder you’re getting
the path to.
Now your script is broken — but you may not notice immediately,
because it doesn’t break with a compilation or runtime error. Instead,
just by moving the
path to statement inside the System Events tell
block, it silently starts returning a different (and wrong)
“Application Support” folder.
For those of you keeping score at home: Radar 4255244.