Tools for Working with AppleScript

Hey Folks,

Most Mac-users don’t know the difference between the various path-types and file-types used in scripting the macOS.

In this thread I’m going to provide some little utilities that make using AppleScript a little easier.

A common beginner AppleScripting issue is to not understand the difference between a POSIX Path and an HFS Path.

A POSIX Path uses forward-slashes to delimit directory nodes in the path:

/Applications/Calculator.app

An HFS Path uses colons to delimit directory nodes in the path:

Mercury:Applications:Calculator.app

As you can see these two path-types have different expectations of where the path should start (the root of the path).

Wikipedia: path
Wikipedia: alias



PUTTING FILE ALIASES ON THE CLIPBOARD


This first script will create a text-list of file aliases and place it on the Clipboard. Use it if/when you are asked to change a file-alias in an AppleScript to work with your system.

It is vital that a file-alias has an HFS Path like so:

set myAppAlias to alias "Mercury:Applications:Calculator.app:"
------------------------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2016/01/16 14:46
# dMod: 2017/02/05 11:43
# Appl: AppleScript
# Task: Finder-Selection to Alias(es) on Clipboard.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Finder, @Selection, @Alias, @Clipboard
------------------------------------------------------------------------------

tell application "Finder" to set finderSelectionList to selection as alias list

if finderSelectionList ≠ {} then
   
   set AppleScript's text item delimiters to linefeed
   set finderSelectionList to paragraphs of (finderSelectionList as text)
   
   repeat with i in finderSelectionList
      set contents of i to "alias \"" & (contents of i) & "\""
   end repeat
   
   set the clipboard to finderSelectionList as text
   
end if

------------------------------------------------------------------------------

Select the file or files you want aliases for, and run the script.

Then paste them into the script you’re working on.

-Chris

[ More to Come ]

6 Likes

Hey Folks,

Now and then on the forum you've heard me refer to a relative alias in connection to AppleScript.

This is very much like a $HOME-based (or tilde-based) Unix path, except there are many more available anchor-points than just the user's home folder.

Here is a tool to create these for you if/when you need one or more for an AppleScript.

-Chris


PUTTING RELATIVE-ALIASES ON THE CLIPBOARD


Keyboard Maestro Macro:

Finder ⇢ Create Relative Alias(s) of Selected Item(s) v1.00.kmmacros (8.9 KB)


Compiled AppleScript:

Finder Selection – Create relative alias(s) and Place on the Clipboard.scpt.zip (14.1 KB)

------------------------------------------------------------------------------
# Auth: Christopher Stone <scriptmeister@thestoneforge.com>
# dCre: 2012/09/22 00:36
# dMod: 2014/09/23 21:40
# Appl: Finder
# Task: Create relative alias(es) to selected Finder item(s) and copy to the Clipboard.
#     : If nothing is selected then the insertion location is used.
# Deps: Uses only OSX components.
# Tags: @Applescript, @Finder, @Alias, @Path, @Reference, @Relative
------------------------------------------------------------------------------
--» PROPERTIES
------------------------------------------------------------------------------
property pathToSpec : {application support, applications folder, desktop, desktop pictures folder, documents folder, downloads folder, favorites folder, Folder Action scripts, fonts, help, home folder, internet plugins, keychain folder, library folder, modem scripts, movies folder, music folder, pictures folder, preferences, printer descriptions, public folder, scripting additions folder, scripts folder, shared documents, shared libraries, sites folder, startup disk, startup items, system folder, system preferences, temporary items, trash, users folder, utilities folder, workflows folder}
------------------------------------------------------------------------------
global expandedPathTo
------------------------------------------------------------------------------

try
   
   set clipboardList to {}
   set expandedPathTo to {}
   
   repeat with i in pathToSpec
      set end of expandedPathTo to path to (get contents of i) from user domain
   end repeat
   
   set AppleScript's text item delimiters to return
   set expandedPathTo to paragraphs of (expandedPathTo as text)
   
   tell application "Finder"
      set fileList to selection as alias list
      if length of fileList = 0 then
         set fileList to target of front window as alias as list
      end if
   end tell
   
   if fileList = {} then error "No items were selected in the Finder!"
   
   set AppleScript's text item delimiters to ":"
   
   repeat with i in fileList
      set end of clipboardList to makeRelativeAlias(i)
   end repeat
   
   set AppleScript's text item delimiters to return
   
   set the clipboard to (clipboardList as text)
   
on error e number n
   stdErr(e, n, true, true) of me
end try

------------------------------------------------------------------------------
--» HANLDERS
------------------------------------------------------------------------------
on makeRelativeAlias(_item)
   global expandedPathTo, pathToSpec
   set _item to _item as text
   set _len to (length of (text items of _item))
   repeat with i from _len to 1 by -1
      set _path to ((text items 1 thru i of _item) as text) & ":"
      if _path is in expandedPathTo then
         repeat with idx from 1 to (length of expandedPathTo)
            if (item idx of expandedPathTo) = _path then
               set refFldr to "path to " & (item idx of pathToSpec) as text
               set diskLocalRef to ("alias " & ("(" & "(" & refFldr & " as text) & ") & "\"" & (text items (i + 1) thru -1 of _item) as text) & "\")"
               try
                  run script diskLocalRef
               on error
                  set refFldr to refFldr & " from user domain"
                  set diskLocalRef to ("alias " & ("(" & "(" & refFldr & " as text) & ") & "\"" & (text items (i + 1) thru -1 of _item) as text) & "\")"
                  try
                     run script diskLocalRef
                  on error e
                     error e
                  end try
               end try
               
               return diskLocalRef
               
            end if
         end repeat
      end if
   end repeat
end makeRelativeAlias
------------------------------------------------------------------------------
on stdErr(e, n, beepFlag, ddFlag)
   set e to e & return & return & "Num: " & n
   if beepFlag = true then
      beep
   end if
   if ddFlag = true then
      tell application (path to frontmost application as text)
         set dDlg to display dialog e with title "ERROR!" buttons {"Cancel", "Copy", "OK"} default button "OK"
      end tell
      if button returned of dDlg = "Copy" then set the clipboard to e
   else
      return e
   end if
end stdErr
------------------------------------------------------------------------------
4 Likes

Hey Folks,

Keyboard Maestro and the shell both depend upon POSIX Paths.

Here’s a script to place POSIX Paths of items selected in the Finder onto the clipboard.

If nothing is selected then the path of the front window is returned.

If no windows are open then the path of the Desktop is returned.

-Chris


PUTTING POSIX PATHS ON THE CLIPBOARD

------------------------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2010/10/06 06:43
# dMod: 2017/04/29 17:32
# Appl: Finder
# Task: Get posix path of selected item(s) or if none the front window and copy to clipboard.
# Libs: None
# Osax: None 
# Tags: @Applescript, @Finder, @Posix, @Path, @Selection, @Clipboard
------------------------------------------------------------------------------

try
   
   set AppleScript's text item delimiters to linefeed
   
   tell application "Finder"
      
      set finderSelectionList to paragraphs of (selection as text)
      
      if length of finderSelectionList = 0 then
         set finderSelectionList to insertion location as text as list
      end if
      
   end tell
   
   if length of finderSelectionList > 0 then
      
      repeat with theAlias in finderSelectionList
         set theAlias's contents to POSIX path of theAlias
      end repeat
      
      set finderSelectionList to finderSelectionList as text
      
      set the clipboard to finderSelectionList
      
   end if
   
on error e number n
   stdErr(e, n, true, true) of me
end try

------------------------------------------------------------------------------
--» HANDLERS
------------------------------------------------------------------------------
on stdErr(e, n, beepFlag, ddFlag)
   set e to e & return & return & "Num: " & n
   if beepFlag = true then
      beep
   end if
   if ddFlag = true then
      tell application (path to frontmost application as text)
         set dDlg to display dialog e with title "ERROR!" buttons {"Cancel", "Copy", "OK"} default button "OK"
      end tell
      if button returned of dDlg = "Copy" then set the clipboard to e
   else
      return e
   end if
end stdErr
------------------------------------------------------------------------------
3 Likes

Hey Folks,

Keyboard Maestro and the shell both depend upon POSIX Paths.

Here’s a script to place Home-Based (Tilde-Based) POSIX Paths of items selected in the Finder onto the clipboard.

If nothing is selected then the path of the front window is returned.

If no windows are open then the path of the Desktop is returned.

A tilde-based POSIX Path uses “~/” to abbreviate your user’s $HOME directory and looks like this:

~/Documents/Action_List.txt

In contrast a full POSIX Path to the same item looks like this:

/Users/YourUserName/Documents/Action_List.txt

Tilde-based paths are very useful, because they are more portable than hard-coded full POSIX Paths.

They can survive disk name changes, user name changes, being moved to a different system.

Believe me — you don’t want to have to change paths in hundreds of scripts after rebuilding your system (or buying a new one).

NOTE — The macOS allows spaces in file names. POSIX Paths do NOT like spaces and therefore they MUST be either escaped or quoted.

Examples of quoted POSIX Paths:

~/'Documents/BBEdit Documents/'
'/Users/chris/Documents/BBEdit Documents/'

NOTE — Be careful to note that you CANNOT quote the “~/” part of the tilde-based path — if you do then you’ll break it.

Examples of escaped POSIX Path:

~/Documents/BBEdit\ Documents/
/Users/chris/Documents/BBEdit\ Documents/

This is sometimes referred to as the “leaning toothpick” method, because a path with many escaped characters can be hard to read.

-Chris


PUTTING HOME-BASED (TILDE-BASED) POSIX PATHS ON THE CLIPBOARD

------------------------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2010/10/06 06:43
# dMod: 2017/05/07 07:14
# Appl: Finder
# Task: Get ~/posix_path/… of selected items or if none the front window and copy to clipboard.
# Libs: None
# Osax: None
# Tags: @Applescript, @ASObjC, @Finder, @Home, @Tilde, @Posix, @Path, @Selection
------------------------------------------------------------------------------
use AppleScript version "2.4" -- Yosemite or later
use framework "Foundation"
use scripting additions
------------------------------------------------------------------------------

try
   
   set homePathPosix to POSIX path of (get path to home folder)
   
   tell application "Finder"
      set fileList to selection as alias list
      if length of fileList = 0 then
         set fileList to insertion location as alias as list
      end if
   end tell
   
   if length of fileList > 0 then
      
      repeat with ndx in fileList
         set ndx's contents to POSIX path of ndx
      end repeat
      
      set AppleScript's text item delimiters to linefeed
      set fileList to fileList as string
      
      set fileList to its cngStr:homePathPosix intoString:"~/" inString:fileList
      
      set the clipboard to fileList
      
   end if
   
on error e number n
   stdErr(e, n, true, true) of me
end try

------------------------------------------------------------------------------
--» HANDLERS
------------------------------------------------------------------------------
on cngStr:findString intoString:replaceString inString:dataString
   set anNSString to current application's NSString's stringWithString:dataString
   set dataString to (anNSString's stringByReplacingOccurrencesOfString:findString withString:replaceString ¬
      options:(current application's NSRegularExpressionSearch) range:{0, length of dataString}) as text
end cngStr:intoString:inString:
------------------------------------------------------------------------------
on stdErr(e, n, beepFlag, ddFlag)
   set e to e & return & return & "Num: " & n
   if beepFlag = true then
      beep
   end if
   if ddFlag = true then
      tell me
         set dDlg to display dialog e with title "ERROR!" buttons {"Cancel", "Copy", "OK"} default button "OK"
      end tell
      if button returned of dDlg = "Copy" then set the clipboard to e
   else
      return e
   end if
end stdErr
------------------------------------------------------------------------------
2 Likes

Hey Folks,

An OSAX is an Open Scripting Architecture Extension. (The plurel is Osaxen.)

They are plug-ins for the macOS that enhance its scriptability and are generally related to AppleScript. In other words they add functionality to AppleScript.

The very best of them is the Satimage.osax (latest stable version) (latest beta version).

It adds a host of features that vanilla AppleScript is missing like regular expression support for find and find/replace, file-globbing, and recursive file/folder listing. It has to be seen and examined to be believed, and I've been a happy user since 2003.

Another favorite of mine is the LapTime.osax which adds finely-grained timing support to AppleScript.

Most neophyte scripters do not know where Osaxen are installed and may not know IF they have been installed.

This macro will produce a report on all installed Osaxen that includes path, name, version, and creation-date.

The output is sent to TextEdit, although that's easy enough to change.

NOTE — Apple installs two:

Digital Hub Scripting.osax
StandardAdditions.osax

Any others will be 3rd Party.


REPORT ALL INSTALLED OSAXEN


Report Installed Osaxen (AppleScript Extensons).kmmacros (3.9 KB)

-Chris

4 Likes

Chris, thanks for sharing this. I'm sure it will be helpful to many.


To Other Readers:

Another common name for OSAX is Scripting Addition. You will see this referred to in many Apple and third party documents.

Some time ago I wrote an Evernote Public Note on this:

Understanding AppleScript Scripting Additions

(You don't need Evernote to read it — it's a web page.)

Satimage.osax Scripting Addition

I second Chris's high recommendation of this great, powerful, reliable, safe, and free Scripting Addition. You can view Documentation (Dictionary) here without downloading it.

It fills in some major gaps in the native AppleScript:

  • Extensive string handling
  • Regular expressions
  • Date handling
  • List handling
  • Sorting
  • and much much more

2 Likes