Refreshing Aliases isn’t so simple: a cautionary tale with Alifix

If you haven’t explored the mind-bending world of Aliases using Precize and Alifix, maybe you should. It’s a classic example of trying to understand the rules when nothing seems to play by them.

A week ago, in my summary on the behaviour of Finder Aliases and Bookmarks, I reported that resolving an Alias would result in updating of its internal data if the path to the linked item had changed. Well it doesn’t, not always, and can’t be relied upon. It’s perfectly possible to resolve an Alias to return a changed path to the linked item, and for the Alias file itself still to retain the old, outdated path.

On the other hand, a lot of things which you might do in the macOS GUI can result in an Alias being resolved, and in some cases these can cause the internal data in the Alias to be updated. The most obvious example is, in a Finder Column view, selecting the Alias to cause the display of a QuickLook thumbnail. The snag here is that it isn’t consistent either: if QuickLook decides that it already has the ‘right’ thumbnail in its cache, it can display the wrong thumbnail for that Alias, and the Alias’s internal data isn’t updated either. On other occasions, the Alias data is updated and the correct thumbnail displayed.

These have made development of my new utility to refresh Aliases and detect broken ones, Alifix, somewhat fraught, to say the least. Version 1.0b1 doesn’t reliably refresh the data in Aliases: sometimes it does, more often than not it doesn’t.

The first step in solving this problem was to select a tool which can reliably show the internal data of an Alias file, using a method which guarantees that examining that data doesn’t cause it to be updated. That may seem an easy task, but once again there are several pitfalls. The answer was the Bookmark Resolver window in Precize: this reads in the contents of the Alias file using NSURL.bookmarkData(withContentsOf:), which doesn’t result in resolution or updating of the data.

Once read in as a Bookmark, Precize then uses URL.init(resolvingBookmarkData:bookmarkDataIsStale:) to resolve the Bookmark data, not the Alias file from which it was taken. This appears a robust way of discovering what’s in an Alias file without altering it in any way. Alifix does the same.

Because of the Finder’s tendency to preview items pointed to by an Alias, via QuickLook, and the fact that it also fetches information about the Alias file itself and the item to which it points, it’s essential when testing to avoid any GUI operation (or command) which might lead to resolution of the Alias. So I have tested Aliases which are safely concealed in folders, and not exposed in a Finder window.

The only time that you have to see the Alias is when selecting it in the Open File dialog in Precize: for that I switch to List view, which doesn’t result in any change in the Alias file itself.

These provide a means for testing out different strategies for refreshing Alias data in Alifix without becoming confused by artefacts.

My first idea was to use one of the calls which definitely results in the Resolver being used on an Alias, URL.init(resolvingAliasFileAt:options:URL.BookmarkResolutionOptions.withoutUI). This creates a new URL by resolving the data in the Alias, here with the essential option of not displaying any dialog prompting the user to fix the Alias if it is broken. In many circumstances, this resolution does result in updating of the Alias data, but in others it does not. Repeated testing using Precize to observe the Alias internal data showed this to be unpredictably unreliable.

This appears to be the case with the few other calls to resolve the Alias itself, rather than the data extracted from it (which, as noted above, never causes the Alias file data to be updated).

The only totally reliable method which I have discovered for forcing the Alias data to be updated is to resolve it into fresh Bookmark data, then write that Bookmark out as new data to the original Alias file, using the sequence
let theNewBMData = try URL.bookmarkData(options: [URL.BookmarkCreationOptions.suitableForBookmarkFile], includingResourceValuesForKeys: nil, relativeTo: nil)
try URL.writeBookmarkData(theNewBMData, to:)

The other question which I have been trying to answer is whether, as I previously thought, it is possible for the data in an Alias file to be updated without changing the file’s last modification datestamp. Although I thought that I had observed this exceptional behaviour previously, I am no longer convinced that it can occur. It certainly doesn’t happen when updating the Alias data using the new method detailed above.

There is one class of Aliases which I have not (yet) attempted to tackle: the new security-scoped Aliases which are intended for use with apps running in a sandbox. These are currently excluded from Alifix, which doesn’t make the necessary call to enable their access.


In this new version of Alifix, there is thus a second checkbox which lets you decide whether or not to force all unbroken Aliases to be rewritten. As for many this is the main purpose of Alifix, it is turned on by default. If you also enable the marking of broken Aliases using the Mark checkbox, this additionally writes out text files with the contents of all Aliases which are rewritten, in case the rewriting process loses any significant information.

A final change is that I have made the scrolling text output view editable, so that users who wish to change its font and size can do so. If you do change those, or edit its contents, when you close the window you’ll be prompted to save its contents: that saving is not currently implemented, so please just cancel that for now.

Alifix version 1.0b2 is now available from here: alifix10b2
and from Downloads above.