Aliasing a File URL / Using a File Reference URL as Link

What for?

Many text-handling programs allow you to drag (or paste) a file into their text field, in order to create a file URL that points to that file.

The problem with this is: Unlike Finder Aliases, file URLs are fragile. They behave like absolute symlinks, that is, they immediately break if you do one of the following:

  • Modify the file name
  • Move it to another folder
  • Modify the name of any of the file’s parent folders
  • Move any of the file’s parent folders

The macro facilitates you to create “aliased” file URLs that will not break if you do one of the above things.

Obviously this is not much needed for rather “static” files, for example files in archived folders, which are unlikely to change.

However, it can be very handy for anything in the context of a work-in-progress project, that is, where file and folder names/paths are subject to potentially frequent change.

Example:

  1. You create a draft of a text and put it into the “Drafts” folder inside your project folder.
  2. Then you create a note “Add ‘blablabla’ to the draft” in your task manager (for example Things or TaskPaper), followed by a link to that draft file.
  3. The project progresses, and later on you decide to rename your “Drafts” folder to “Drafts – Chapter 01”.

If your link to the draft file was a regular file URL, then that link is broken now. Instead, if you’d created the link with this macro, it would still be working.

Background

For most things I’m using Things as my task manager (sometimes TaskPaper). Up until recently Things had a really superb and outstanding feature: If you dragged a file to Things, Things stored the link to that file as alias data inside its database. The link in Things behaved exactly like a Finder Alias, i.e., pretty hard to break.

For some opaque reasons they decided to remove that feature, and a file dragged to Things now creates an ordinary file URL. Just like in TaskPaper and other similar apps. So I was looking for a solution, and this macro is the best I can come up with, ATM.

Basically just trying to replace the bygone feature of Things, but the macro is also usable with other apps.

How it works

  1. The macro creates aliases of your Finder-selected files/folders at a pre-defined location.
  2. It gets the file URL and the file name of these aliases and puts this info in a formatted form to the clipboard.

How to use

  1. Select the file(s) or folder(s) you want to link to in the Finder.
  2. Run the macro.
  3. Go to your task manager (or any other text-handling app) and paste.

Result (example with Things):

09-pty-fs8

Normal result of dragging a file (without macro):

24-pty-fs8

Note: In contrary to what the images might suggest: The point is not to make the file URL shorter. It’s a side effect.

Tips

Location of the alias hub

You can set the location where the alias files will be stored (the “alias hub”) in the contained AppleScript.

Choose a short folder name and a short path, in order to get a compact URL. The default is set to “alias” at the root of your Home directory. (~/alias/)

Link format

The script is set to paste a link in the format
<file name><separator><file URL>

You can change the separator in the AppleScript. For a newline use linefeed (not quoted).

Caveats

Duplicate file names

If you create a file alias that already exists in the alias hub directory, it will be created with an “alias” suffix (and later on with “1”, “2”, etc.). This is the Finder’s usual behavior. This might not be optimal, but I think it is quite OK, as it makes sure that you always get a working alias and at the same time you are adverted of a possible redundancy.

The aliased file URL will be created correctly, no matter how many duplicate aliases you create.

Aliases can break too

Aliases are pretty robust to path/name changes. But they can break, too. If this happens, then you would be better off with a regular file URL, since it provides a clue to the last file location before it broke.

An option would be to append the literal path of the source file at the time of creation to the link. But, I think, the resulting link text would just be uncomfortably longish for the 97% of the cases where the alias does not break.

The macro

Compared to my description the macro/script is very compact :slight_smile:

Set the hotkey to your needs.

Alias File URL.kmmacros (3.0 KB)

The script content of the macro:

  # Some settings
  # The location where the aliases should be stored. Use a short name and path to keep the URL short.
  set aliasHub to (path to home folder from user domain as text) & "alias"
  # The filename/fileURL separator for the URL display
  # For example " — " will create this: "Test File.txt — file:///Users/tom/alias/Test%20File.txt"
  set theSeparator to " — "
  
  set niceURL to {}
  
  tell application "Finder"
    # Create aliases from the Finder selection in the alias hub
    set theSelection to the selection as alias list
    set theAlias to (make alias at aliasHub to theSelection) as list
    # Get properties and construct a nice file URL
    repeat with i in theAlias
      set {theName, theURL} to {displayed name of i, URL of i}
      set the end of niceURL to theName & theSeparator & theURL
    end repeat
  end tell
  
  # Put it to the clipboard as text
  set {saveTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {linefeed}}
  set the clipboard to niceURL as text
  set AppleScript's text item delimiters to saveTID

I guess the script could also be made as a pure/native KM macro, but it is an AppleScript, because initially it was created for use with LaunchBar.

Notes

Above I often mentioned apps like Things and TaskPaper, but the script of course will also serve when pasting into any other app that can handle text.




Addendum 2019-05-15:

A different approach

Another approach, to achive basically the same, is by using file reference URLs.

A file reference URL looks like this:

file:///.file/id=6571367.8706809504

Instead of the file path (as with a normal file URL) it contains the inode number of the file (the “8706809504” in the example above). The first number is likely some volume identifier.

Here a variant of the above script that will copy the file reference URLs of the Finder-selected items to the clipboard (along with the file name, as in the script above):

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

# The filename/fileURL separator for the URL display
# For example " — " will create this: "Test File.txt — file:///.file/id=6571367.8706809504"
set theSeparator to " — "

set niceURL to {}

tell application "Finder" to set theSelection to the selection as alias list
# Get properties and construct a nice file ref URL
repeat with i in theSelection
  tell application "Finder" to set {theName, thePath} to {displayed name of i, POSIX path of i}
  set theURL to (current application's class "NSURL"'s fileURLWithPath:thePath)
  set theRef to theURL's fileReferenceURL()
  set theRef to theRef's absoluteString()
  set the end of niceURL to theName & theSeparator & theRef
end repeat

# Put it to the clipboard 
set {saveTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {linefeed}}
set the clipboard to niceURL as text
set AppleScript's text item delimiters to saveTID


File Reference URL.kmmacros (3.1 KB)

Pasted into Things it looks like this:

00

Advantages

  • More elegant; you don’t have to create an “alias hub” folder on disk.
  • The resulting URL is likely to be shorter than a file URL

Disadvantages (?)

  • The only reference to the file is the inode number. So, I’m not sure if it is as reliable as an Alias.

    • The bookmark data inside an Alias also contains the inode number, but in addition much more information on the destination file; for example the original path, which gets updated – at least – each time you resolve the Alias.

    • On the other hand, I’m not sure if an inode number can break at all (?). And if it breaks, I’m not sure if the Finder would make good use of of the other bookmark information contained in an Alias, in order to locate the “missing” file. [1]

  • Not much tested.


1: One case where a mere file reference URL will fail (because the inode changes) and an Alias should/could continue to work, is when you move your whole folder hierarchy (including Alias and destination file) to a different volume. For this to work it seems to be required though that the path info inside the Alias is up to date before moving the files. (Either by double-clicking or using a tool to batch-resolve Aliases.)

2 Likes

Update 2019-06-19

Sorry, my original post is locked for updating, for whatever reason. So, a new post instead.

Well, here again a new update of my script:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions


# SETTINGS

# Here you can manipulate the output of the script to your needs, or to the needs of the app you are going to paste the output in.

# Mode
# If we should get…
# (1) the file reference URL
# (2) the file URL
# (3) the file URL + the file reference URL
set URLMode to 1
-- set theMode to 2
-- set URLMode to 3

# File/folder icons
# The icon displayed before the file/folder name (including any space character in-between the icon and the name).
# Set them to an empty string if you don't want to have icons.
-- set {fileIcon, folderIcon} to {"📄 ", "📁 "} # Some standard icons
set {fileIcon, folderIcon} to {"", ""} # No icons

# The characters that should enclose the file name
# You can eliminate one or both by using an empty string.
# Having a leading and a trailing separator allows you to put the ref URL into some kind of brackets (e.g. for Markdown).
set {fileNameLeading, fileNameTrailing} to {"[", "]"} # File name wrapped in brackets (works with Markdown)
-- set {fileNameLeading, fileNameTrailing} to {" ", " — "} # Only a spaced em dash after the file name, no leading character

# The characters that should enclose the file reference URL
# You can eliminate one or both by using an empty string.
# Having a leading and a trailing separator allows you to put the ref URL into some kind of brackets (e.g. for Markdown).
set {refURLLeading, refURLTrailing} to {"(", ")"} # Ref URL wrapped in parenthesis (works with Markdown)
-- set {refURLLeading, refURLTrailing} to {" 〈", "〉 "} # Ref URL wrapped in Angle Brackets
-- set {refURLLeading, refURLTrailing} to {" — ", ""} # Only a spaced em dash before the ref URL, no final character

# The characters that should enclose the file URL
# You can eliminate one or both by using an empty string.
# Having a leading and a trailing separator allows you to put the ref URL into some kind of brackets (e.g. for Markdown).
set {fileURLLeading, fileURLTrailing} to {"(", ")"} # File URL wrapped in parenthesis (works with Markdown)
-- set {fileURLLeading, refURLTrailing} to {" 〈", "〉 "} # File URL wrapped in Angle Brackets
-- set {fileURLLeading, refURLTrailing} to {" — ", ""} # Only a spaced em dash before the file URL, no final character

# The filename/URL separator  
# If using both URLs the resulting URLs string will likely not fit in the same line as the file name, so maybe probably nicer to separate with a line break right away.
-- set nameURLSeparator to linefeed
set nameURLSeparator to ""


# SCRIPT

set niceURL to {}

tell application "Finder" to set theSelection to the selection as alias list
# Get properties and construct a nice file ref URL
repeat with i in theSelection
  set theIcon to fileIcon
  tell application "Finder"
    set {fileName, filePath} to {displayed name of i, POSIX path of i}
    if kind of i is "Folder" then set theIcon to folderIcon
  end tell
  set fileURL to (current application's class "NSURL"'s fileURLWithPath:filePath)
  set refURL to fileURL's fileReferenceURL()
  set {fileURL, refURL} to {fileURL's absoluteString(), refURL's absoluteString()}
  if URLMode is 3 then
    # Getting both the file URL and the reference URL
    set the end of niceURL to fileNameLeading & theIcon & fileName & fileNameTrailing & nameURLSeparator & fileURLLeading & fileURL & fileURLTrailing & refURLLeading & refURL & refURLTrailing
  else if the URLMode is 2 then
    # Getting only the file URL
    set the end of niceURL to fileNameLeading & theIcon & fileName & fileNameTrailing & nameURLSeparator & fileURLLeading & fileURL & fileURLTrailing
  else
    # Getting only the file reference URL
    set the end of niceURL to fileNameLeading & theIcon & fileName & fileNameTrailing & nameURLSeparator & refURLLeading & refURL & refURLTrailing
  end if
  
end repeat

# Put it to the clipboard 
set {saveTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {linefeed}}
set the clipboard to niceURL as text
set AppleScript's text item delimiters to saveTID

What's new:

  • Better explanations in the Settings part of the script
  • Added setting for only using the file URL (see the Note below)
  • For compatibility with Markdown targets (like Bear) now you can fully customize the parenthesis for the file name, the file ref URL and the file URL.
    • The default settings now are Markdown-ish:
      [<file name>](<file reference URL>)

With the example text from above and the new default settings, it looks like this in Bear:

14-pty-fs8

47-pty-fs8

…and in Things (which doesn’t have a Markdown interpreter):

45-pty-fs8

I think, this a reasonable default setting: it works perfectly in Markdown-aware apps, and it’s not too ugly in plain-text apps. If you only ever paste into plain-text apps (Things, TaskPaper) then of course you should change the settings in the script to something visually more attractive.

Note:

In many apps the file reference URLs work as expected (you click the link and the destination file/folder will be shown in the Finder). However I noticed that in some apps they don’t: you get a “does not have permission to open” error.

This concerns for example iA Writer, Agenda. I guess, these apps are trying to open the linked file (instead of showing it in the Finder) and then hit some sandbox restrictions.

Interestingly, when using the file URL (not the file ref URL) these apps work correctly, i.e., they reveal the destination file in the Finder. So, if this problem hits you, you have to set URLMode to 2 or 3.

2 Likes