Links and aliases beyond local files: advanced file system techniques

My previous article on links and aliases concentrated, for simplicity’s sake (!), on references to files. Although I know some found that challenging enough, others are keen to expand coverage to include folders/directories and more complex situations and usage. I can see this turning into a whole series, but here is some additional detail.

You can see complex effects when mixing link/alias types, which can work to your advantage at times. For example:

  1. Create a Finder Alias to a file, on the same volume.
  2. Create a hard link to that same original file, on the same volume.
  3. Delete the original file, to which both the Finder Alias and hard link point.
  4. Now the Finder Alias points at the hard link, not the missing original file. This is because of its fallback to using inode numbers when the absolute path no longer works. As the inode number of the hard link is identical to that of the original file, the alias now finds that instead.

If you try the same using symlinks, the symlink breaks at step 3, of course.

Folders/directories

Links and aliases to folders or directories are different in many ways to those of mere files. Most of the time, you use links to files as a means of making it easier to access a file which might need to be buried in an otherwise inaccessible place.

I try to keep reference files used for articles in this blog in a structured hierarchy, so I know where to look to find them again, in theory at least. But when I’m working on a new article, I may want to make it easier to access one or more files directly from higher up in the hierarchy: a link or alias is an excellent way of doing that, as I can just open that link or alias whenever I want to access that document.

When you want to access a whole folder from another place, your use of links is more than just locational convenience, but becomes a matter of navigation. Rather than moving the deeply-buried folder to somewhere more accessible, an easier solution is to make a link/alias to that folder on your Desktop or somewhere else equally convenient. You might want similar if your internal storage is too small to contain all your Home folder, and you relocate parts of it (or the whole) to an external disk.

Different types of link/alias to a folder behave in different ways, depending on how you access them:

  • APFS clones don’t currently work with folders. If you Option-drag a folder to another location on the same volume, APFS performs a regular copy of the folder and its entire contents. This is probably what you’d expect when copying a normal folder, but can catch you out when it’s a folder posing as a file, such as an app or other bundle.
  • Symbolic links work best when accessed from the command line, or in scripts. Because those methods of access are based on Unix conventions, any operation which works in Unix should work fine with a Mac symlink, such as changing directory with the cd command, listing contents, and so on. The Finder also copes well working with symlinks to folders. However, you must remember that a symlink only contains a relative path to the folder – the path that is necessary from the symlink’s location, not from the root of your filesystem, unless that’s what is required. Do anything to break that relative path, and the symlink stops working. So a symlink is best when neither the link nor the target will move or be renamed.
  • Hard links to directories aren’t supported in APFS, although they still are in HFS+. Because of this, you should only ever use directory hard links on volumes which are guaranteed to remain in HFS+ format, such as Time Machine backups, which for the time being rely on directory hard links to work. There is no sign that Apple is likely to change this in APFS, but is more likely to change the structure of Time Machine backups instead.
  • Finder Aliases to folders are only resolved by the Finder, or by calls to macOS. They are not resolved at the command line, nor in command scripts. As far as commands are concerned, a Finder Alias is a file, not a link. However, Finder Aliases are resolved in the Finder (the name is a clue!), and should always be resolved by apps (see below). So if you’re going to access a linked folder using the Finder and apps but not in Terminal or its scripts, they are good to use.

Behaviour in apps

Developers have many different ways of definining a path to a file or folder. Depending on which they use in an app, they can break any or all of the above apart from a hard link, although I’m sure that someone at some time has even managed to break them!

The very worst way that code can handle the path to a file or folder is using a string to its relative or absolute path, e.g. /Users/username/Library/Preferences/ThisApp/Resources.data. If that precise path can’t be found, then the file can’t be opened. This makes such hard-coded paths safe only if they’re within parts of macOS which are protected by SIP; the further you move away from those, the more prone they become to breakage.

Files which are chosen in standard Open File dialogs are least likely to be a problem, as the dialog returns them as a URL, which undergoes resolution of all types of link and alias, including any Finder Alias.

There’s a lot that can go wrong in between those, for both links to files and those to folders. With the advent of the sandbox, iCloud and APFS, though, all modern apps which are compatible with those should be using methods to access files and folders which resolve both symbolic links and Finder Aliases. If they struggle with either, then the chances are they’re not going to survive much longer, particularly with macOS 10.15 expected later this year. It’s time to upgrade or replace them.

iCloud

As you might guess, copying links/aliases to iCloud Drive brings further complications to their behaviour. In general, macOS treats this as if they were copied to another volume. So:

  • Symbolic links are copied as they stand, with their relative path intact. If that happens to point to the right file or folder, then they continue to work. If the original to which they point isn’t copied to the same path relative to the link, they break.
  • Hard links are treated as separate files, so copying a hard link is the same as copying the file to which it links, but under the name of the link. This breaks their linkage, as changing the file to which they were originally linked doesn’t alter the content retrieved from the hard link, which is now a new file in iCloud.
  • Finder Aliases behave in one of two ways, according to whether the file to which they point is present in the same relative path. If it is, then they behave like symlinks and link to that file in iCloud. If the original isn’t copied to iCloud, then they link back to their original in local storage. Although a pragmatic solution, and preferring to link to what is available locally in iCloud, this can have unexpected effects if an original is inadvertently left on local storage when it was intended to copy that to iCloud as well.

Bookmarks and Finder Aliases

A Finder Alias is but one implementation of what Apple calls a Bookmark, which contains similar opaque data including the absolute path and inode number. My free command tool alisma creates Bookmark files which are functionally identical to Finder Aliases using the Swift code:
let theData = try theOrigURL.bookmarkData(options: [URL.BookmarkCreationOptions.suitableForBookmarkFile], includingResourceValuesForKeys: nil, relativeTo: nil)
try URL.writeBookmarkData(theData, to: theAliasFURL)

Although primarily intended for creating and resolving such aliases from the command line, alisma‘s Bookmark files work perfectly well in the Finder. alisma also extracts absolute paths from both Finder Aliases and its own Bookmark files. You can create and resolve Bookmarks in my free app Precize.

Bookmarks can go beyond functioning as smart symlinks too. They include support for ‘Security Scope’ which can impose limitations on what can be done to the linked file, which includes allowing read only access, even though Unix permissions may be more liberal. These are intended for use in apps which run in a sandbox, and only appear to be functional when running there.