Recreate an alias with the same name and timestamp programmatically

aliasapplescriptfilesystemfinderservices

Let us develop a utility to batch process legacy alias files.

Implemented as:

  • Finder File Service,
  • Automator Workflow,
  • Applescript,
  • Shellscript,
  • or whatever else that those the job.

Per each file in the batch this should be done:

  1. Is the file an alias? (avoid other file types supplied by user error)
  2. Get its filepath, filename, timestamp, label, tags.
  3. Delete it.
  4. Recreate it at the original filepath with the determined filename, timestamp, label, tags.

Followup: I filed a bug report to Apple, see below. Maybe Apple comes up with a solution. But I think some skilled AppleScripter(s) here can come up with a solution within minutes. Would be cool, if we find a solution here, and offer it to the whole macOS community.


Bug report to Apple, filed on 2017-01-10

Finder / HFS+ / filesystem — Refreshing legacy alias files to reduced filesize with batch process

A LONG LASTING BUG WAS LUCKILY FIXED:

In macOS Sierra the file size of aliases was finally reduced dramatically, from multiple megabytes in Mac OS X 10.7-10.11 systems down to only about 1 KB now in macOS Sierra 10.12. (Simply by not including the icon resources, which where mostly anyhow redundant being just a copy of a generic file type icon.)

PLEASE OFFER A FIX FOR THE BUG LEGACY AS WELL:

Depending on how heavily aliases are used on a system, there is the potential to save multiple GBs for some users.

I propose to Apple to offer a batch process for reducing the file size of legacy alias files. With an option to preserve the aliases' original timestamps, as they may have critical information value in some use cases.

Then you could do a simple Finder search, select the files of your liking (all or only certain) and then drag'n'drop them onto the batch process app or file service or Finder menu command.

CURRENT WORKAROUND WITH QUICKLOOK ONLY WORKS PARTIALLY

  1. Finder > New window (cmd-N) > Search (cmd-F)
  2. The search criteria show up, set them as follows:
    • "Kind" is "Other", type in "Alias"
    • You get a Finder search result window.
  3. View as list and sort by size.
    • Then you have the top file size culprits on top.
  4. If you QuickLook a file via SPACE-key then no alias recreation occurs.
  5. Issue "File > Show Original" (cmd-R) on the selected file.
  6. In the newly opened window, QuickLook the alias files with SPACE.

Then certain alias files get recreated. But not all!

Working, but only sometimes: PDF, JPEG, ZIP if BetterZip QuickLook plugin is the handler.

Out of these not all aliases get refreshed.

It seems to also depend on the file's overall or individual associated application (Finder "Open with" setting, Uniform Type Identifier (UTI), TYPE/CREATOR resource fork) and which QuickLook plugin handles the file type.

An recreated file has a dramatically reduced file size (bout 1 KB). Sadly it looses its original timestamp, but gets the current one (equivalent to /usr/bin/touch). I would love to keep the alias timestamp preserved.

Best Answer

Create a Service with Automator — Tested on macOS Sierra

  1. Open /Applications/Automator.app
  2. File > New (cmd-N)
    • Choose a type of document: "Service".
  3. Service receives selected: "files or folders" in "Finder".
  4. In the left pane navigate to: Actions > Library > Utilities > Run AppleScript.
    • Drag the "Run AppleScript" item from the library pane on the left to the source code pane on the right.
  5. Clear the prefilled content entirely. Paste in the following source code:

AppleScript Source Code

use framework "Foundation" -- Cocoa-AppleScript

on run {input, parameters}
    repeat with thisItem in input
        tell application "Finder"
            if kind of thisItem is "Alias" then -- alias file only
                set parentPath to container of thisItem -- get the folder of this alias
                set {label index:l, comment:c, modification date:m, creation date:cr, original item:origPath, name:n} to properties of (item thisItem)
                if origPath is not missing value then -- not a breaking alias
                    set tagsList to (my tagsFor:(POSIX path of thisItem)) -- get the tags of the alias file (call an AppleScriptObjC handler)
                    delete thisItem -- move this alias to the trash

                    -- ** create an alias file **
                    set newAliasFile to make new alias at parentPath to origPath with properties {comment:c, creation date:cr, original item:origPath, name:n}
                    -- ** set the label ** (0 = no label)
                    if l is not 0 then set label index of newAliasFile to l
                    -- ** set  the tags ** ({} = no tag) 
                    if tagsList is not {} then (my setTags:tagsList forPath:(POSIX path of (newAliasFile as string))) -- call an AppleScriptObjC handler
                    -- ** change the modification date **
                    set modification date of newAliasFile to m
                end if
            end if
        end tell
    end repeat
end run

on tagsFor:posixPath -- Cocoa-AppleScript handler 
    set fileURL to current application's |NSURL|'s fileURLWithPath:posixPath
    set {theResult, theTags} to fileURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
    if theTags = missing value then return {} -- no tags
    return theTags as list
end tagsFor:

on setTags:tagList forPath:posixPath -- Cocoa-AppleScript handler
    set fileURL to current application's |NSURL|'s fileURLWithPath:posixPath
    fileURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end setTags:forPath:
  1. File > Save (cmd-S): Give it a name like "Alias recreation".
  2. Open System Preferences > Keyboard > Shortcuts > Services > Files and folders > Alias recreation, or however else you named it.
    • Assign it a shortcut. As cmd-L is used to create an alias (L as in "link"), I assigned it cmd-alt-ctrl-L.
  3. Select one or multiple legacy alias files, and process them.
    • With your shortcut cmd-alt-ctrl-L.
    • or through the main menu: Finder > Services > Files and folders > Alias recreation.

Note: The batch process is very transparent and mistakes can be corrected. The deleted aliases are moved to your Trash bin. Should you have made a mistake choose the trashed alias file in question and run Finder > Put back (cmd-backspace). This will put the file back in its previous parent folder and open the parent folder in a new window. Then you have the recreated alias and the original alias with the suffix " copy" side by side and can make corrections if necessary.