Oops: It looks like this may actually be a bug in AppleScript, according to hhas below. It completely fooled me, because the behaviour is logical and explainable. I’m leaving this post here, because it’s still somewhat informative, but its basic point about the exists
command may be incorrect. Please read hhas’s post below.
I would like to expand on this, since newcomers typically don’t know what’s going on here. I don’t think I’ve seen it discussed in detail before on the forums, but I haven’t searched for it, so I may be retreading.
First, some background.
EVERY EXISTENCE HAS A BEGINNING
Everything in programming, at some point, comes back to how memory is handled. Strings are not an exception, and in fact they’re a really good example to get us going and lay some foundation work.
IN THIS CORNER, weighing in at an UNKNOWN AMOUNT OF BYTES, is a string that is dynamically allocated during runtime:
set aString to (choose file with prompt)
AND IN THIS CORNER, weighing in at EXACTLY AS MANY BYTES AS IS NEEDED TO STORE “pants”, is a string that is statically allocated at compile time:
set aString to "pants"
What’s the difference between dynamically and statically allocated strings? You typed the string into the source code, so the compiler knows exactly how long, in memory, the value of the variable needs to be; you’ve essentially told the compiler how much data the program will need to store in memory by defining the exact string, and thus its length. Compilers are smart that way–since they know how large certain data types are, they can figure out certain optimizations when given the right information. (Such as an exact string typed into the source.)
In C, for example, “pants” is exactly 6 bytes long. (Five characters plus one null character to mark the end of the string.) It will always be 6 bytes long when the program loads, so the compiler can gain a tiny resource gain by shoving those 6 bytes into an unchanging–static–memory location.
The first version, however, requires the user to choose a file. The compiler has no way to know what file the user will choose, so it can’t make the same kind of optimization–the user might pick a path whose length is 26 bytes, 67 bytes, or 900 bytes. Because of this, we say it’s dynamically allocated.
We’re going to move away from strings for just a moment, so follow along.
WHAT DOES THIS HAVE TO DO WITH exists
? (AND OTHER COOL FACTS ABOUT GEOGRAPHY)
Let’s say you have an AppleScript command that returns some object. You don’t really know how it works internally–it’s part of a larger library you’re using–and it doesn’t really matter. You just know that using the command will either return you some object or result in nothing at all.
if exists (window 7 of application "Camino") then
doStuff()
end if
If the window object exists, you’ll fall through the branch and call doStuff. If not, you’ll skip past and continue executing code.
The key here is that exists
tests for the existence of an object in memory, basically. It doesn’t know what paths, folders, disks, songs, windows, or other things are specifically. If the target application returns an object from whatever command it was given, that’s all exists
cares about.
It’s the difference between asking a road map if Iowa exists and actually going to Iowa and seeing what’s there. The map might tell you that yes, Iowa exists, but then you look to see what Iowa is, and it’s actually a giant amusement park 3 miles wide, instead of a mid-sized U.S. state.
You: “Does Iowa exist?”
Exists: “Yes, Iowa is there.”
-vs-
You: “Does a U.S. state called Iowa lie at the end of Route 123?”
Exists: “That isn’t what I do. Ask an application that understands what roads and states are. But I’ll tell you ‘yes’ anyway.”
You: What?
IF EXISTS (BIG FINISH) THEN
So why would this always fall through and show a dialog, even when I don’t have the specified file on my Desktop?
if exists "MacHD:Users:mikey:Desktop:INTERNET_CHEAT_CODES.txt" then
display dialog "you got the internet cheat codes!"
end if
Because even when I don’t have the file, I’ve still typed that string directly into the source code. It isn’t going to change, so the compiler statically allocates an AppleScript string object for it. It will always exist in memory, so exists
will always evaluate to true.
And that is why “exists” always says something exists when you specify a string in your code in AppleScript.