Is it possible to script what applications should open certain file extensions?
As far as I know, all file associations are defined on the launchservices.secure.plist file.
For macOS Mojave/Catalina this file is located at:
~/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist
You can read the file contents using:
defaults read ~/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist
This command will output on terminal the file contents, which has each associated application with the corresponding file types.
Sample output:
$ defaults read ~/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist
{
LSHandlers = (
{
LSHandlerContentType = "public.3gpp";
LSHandlerPreferredVersions = {
LSHandlerRoleAll = "-";
};
LSHandlerRoleAll = "com.colliderli.iina";
},
{
LSHandlerContentType = "org.7-zip.7-zip-archive";
LSHandlerPreferredVersions = {
LSHandlerRoleViewer = "-";
};
LSHandlerRoleViewer = "com.aone.keka";
},
{
LSHandlerPreferredVersions = {
LSHandlerRoleAll = "-";
};
LSHandlerRoleAll = "com.apple.dt.xcode";
LSHandlerURLScheme = xcpref;
},
{
LSHandlerContentType = "public.html";
LSHandlerPreferredVersions = {
LSHandlerRoleAll = "-";
};
LSHandlerRoleAll = "com.apple.safari";
}
);
}
I cannot fully answer your question now, but this is the starting point to look at and understand how those parameters works, and after testing and figuring it out we can expand this information with complete details and some examples of edited working versions.
But for the specific situation, considering the case of making a kind of template to just to replicate, (or to have it stored as a backup):
I suggest you could manually customize one system the way you want it, by traditional Finder file associations methods, and once it is fine, you save that .plist file, then you can replace that .plist file on the new system, or on the new user profile, and [reboot?, logout?, or kill finder?] and login again, and this should be enough for the associations be replicated and ready.
[Comments and edits are welcome]
There is a command line application that can do this for you, it is called Duti and it is availible at https://github.com/moretension/duti . I compiled a version of Duti using Macports, and then dropped that utility in the Resources folder inside a script application wrapper, and call it using a "do shell script". I have tried it on multiple machines at work and it works every time!.
Here is my code for using Duti:
try
tell application "Finder"
set icon_path to (container of (path to me) as alias)
set temp_path to POSIX path of (container of (path to me) as alias)
set current_path to temp_path & "ChangeDefaultAdobeApps.app/Contents/Resources/"
set iconPath to (icon_path & "ChangeDefaultAdobeApps.app:Contents:Resources:adobe_apps_software_icon_512.icns" as string) as alias
end tell
set jpgScript to current_path & "duti" & space & " -s com.adobe.Photoshop public.jpeg all"
do shell script jpgScript
set pdfScript to current_path & "duti" & space & "-s com.adobe.Acrobat.Pro com.adobe.pdf all"
do shell script pdfScript
set tiffScript to current_path & "duti" & space & " -s com.adobe.Photoshop public.tiff all"
do shell script tiffScript
display dialog "Settings Changed!" buttons {"OK"} default button "OK" with icon iconPath
on error
display dialog "Something Went Wrong" buttons {"Cancel"} default button "Cancel" with icon 0
end try
An application registers the types of items that it can handle by putting entries into its Info.plist. The CFBundleDocumentTypes
key is an array of dictionary entries describing the document types (name, icon, role, etc - see the Information Property List Key Reference). For example, an application I use to provide a couple of custom document icons has these entries:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeIconFile</key>
<string>ruby-script_Icon</string>
<key>CFBundleTypeName</key>
<string>Ruby Source</string>
<key>CFBundleTypeRole</key>
<string>None</string>
<key>LSItemContentTypes</key>
<array>
<string>public.ruby-script</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFile</key>
<string>property-list_Icon</string>
<key>CFBundleTypeName</key>
<string>Property List</string>
<key>CFBundleTypeRole</key>
<string>None</string>
<key>LSItemContentTypes</key>
<array>
<string>com.apple.property-list</string>
</array>
</dict>
</array>
The app is just a proxy for the target application and is created by copying the following script into the Script Editor and saving it as an application, then copying the icon resources and editing its Info.plist. It doesn’t really do anything but open files in the application I want (BBEdit in this case), but you could also perform other setup routines:
on open droppedItems
-- perform setup or whatever
set args to ""
repeat with anItem in droppedItems
set args to args & quoted form of (POSIX path of anItem) & " "
end repeat
do shell script "open -b com.barebones.bbedit " & args
end open
From there, I just use Finder’s Get Info window to make the proxy app the default application for those file types. Using this approach I can assign custom icons, with double-click and drag operations that open the document(s) as usual, without having to alter the target application.