Is this new? If I try to coerce text to an alias to an item that does not exist because the startup drive is missing from the front of the the text string, appleScript “helpfully” adds the startup disk to the string. Took me quite a while to figure out why I was getting this behavior.
The ASLG says: “HFS paths with a leading colon, such as “:folder:file”, are resolved relative to the HFS working directory. However, their use is discouraged, because the location of the HFS working directory is unspecified, and there is no way to control it from AppleScript.”
But the string in this script (below) doesn’t have a leading colon.
Is this a bug?
set partialPath to "Library:Scripts:"
tell application "Finder"
set isPathGood to exists item partialPath -- false
end tell
set aliasFromPartialPath to partialPath as alias
--alias "Macintosh HD:Library:Scripts:"
If you mean is it recent, I suspect not. POSIX path has always exhibited the same behavior, and they probably use similar approaches.
It’s academic at this stage – HFS paths are deprecated, and nothing to do with them is likely to change. But it certainly supports Chris Nebel’s objection to using as alias as a way to verify that a file exists.
OTOH, Chris was a big fan of using System Events rather than the Finder. The deprecated Standard Additions commands like list folder, for example, suggest using System Events, not Finder. But sadly:
set partialPath to "Library:Scripts:"
tell application "System Events"
set isPathGood to exists disk item partialPath --> true
end tell
The best solution is to avoid relative HFS paths – they’ve never been reliable for the reasons Ed quoted from the ASLG above.
At the application level, most stuff is being done with NSURLs and POSIX paths – doing it via HFS stuff is deprecated. And there’s one deprecated (C-based) function for doing the conversion. It’s that function that’s returning what you see here.
It may be that the Finder is still using Carbon HFS functions, or it may be building file references internally, and doing it’s own path parsing as part of that process.
I guess the way to do it in ASObjC would be to create an NSURL, and then compare the name of its volume with the first part of the HFS path. To be doubly sure, you’d probably need to ignore case (and that’s also going to depend on whether the volume supports case-sensitive paths).
If you can retrieve the volume, the NSURL exists, so a match of volume names is all you should need. Something like:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
set partialPath to "Library:Scripts:"
set posixPath to POSIX path of partialPath
set partialPath to current application's NSString's stringWithString:partialPath
set hfsVolumeName to (partialPath's componentsSeparatedByString:":")'s firstObject()
set theURL to current application's |NSURL|'s fileURLWithPath:posixPath
set {theResult, theValue, theError} to theURL's getResourceValue:(reference) forKey:(current application's NSURLVolumeNameKey) |error|:(reference)
set isPathGood to theResult as boolean and (theValue's lowercaseString()'s isEqualToString:(hfsVolumeName's lowercaseString())) as boolean
That’s a lot more code than simply asking the Finder. Nonetheless, it’s also more than 10 times faster, so if you want to check a lot of paths, it might still be a better option.
But the fact that this whole issue comes up so rarely suggests it’s generally more an academic problem. I don’t think many people use relative HFS paths.
But they’re not what we’re talking about here – you’re effectively building paths at run time, and relevant to the startup disk. The issue Ed raised is a complete HFS path provided as a string when the named volume isn’t available.
Right – you’re avoiding the problem by not using an HFS path.
I did mention that I’d almost forgotten about this bug, and why.
The last time I got bit by it was some time around 2004-5, and was one of several reasons I started using systems to prevent that sort of thing from happening.
For what it’s worth, those are exactly the kinds of commands I am using in this script.
The script is syncing files to an archive. When the script gets an alias to a file that’s going to be synchronized, it removes the reference to the startup disc, and replaces is it with the path to the folder for those items.
(With “LocalStartupDrive” being replaced with the name of the startup drive)
When downloading a file from the remote directory, if the script has to know if the file already exists. If it does exist, it checks modification dates and decides if it should be replaced. If it doesn’t exist, it duplicates it to that location.
Old timer AS people like me still use them when I am too lazy to do a lot of typing. Unfortunately I’m too lazy far to much. Of course when that function no longer works at all it will be a big pain to fix preexisting files. But why fix today what you can fix tomorrow. But in all seriousness someday it will just break all together, if they don’t remove it before that time.