How to Change the Default Application for a Specific File?

Hey Folks,

Does anyone know how to script changing the default application for a specific file?

(Not a file type / extension – although I’d like to learn how to do that too.)

It looks like macOS (on Mojave at least) simply writes an xattribute to the file:

com.apple.LaunchServices.OpenWith:
00000000  62 70 6C 69 73 74 30 30 D3 01 02 03 04 05 06 57  |bplist00.......W|
00000010  76 65 72 73 69 6F 6E 54 70 61 74 68 5F 10 10 62  |versionTpath_..b|
00000020  75 6E 64 6C 65 69 64 65 6E 74 69 66 69 65 72 10  |undleidentifier.|
00000030  00 5F 10 18 2F 41 70 70 6C 69 63 61 74 69 6F 6E  |._../Application|
00000040  73 2F 44 72 61 66 74 73 2E 61 70 70 5F 10 1C 63  |s/Drafts.app_..c|
00000050  6F 6D 2E 61 67 69 6C 65 74 6F 72 74 6F 69 73 65  |om.agiletortoise|
00000060  2E 44 72 61 66 74 73 2D 4F 53 58 08 0F 17 1C 2F  |.Drafts-OSX..../|
00000070  31 4C 00 00 00 00 00 00 01 01 00 00 00 00 00 00  |1L..............|
00000080  00 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
00000090  00 6B                                            |.k|
00000092

My default text editor is BBEdit, and I’ve obviously set the above file to Drafts.

I’ve been Googling and so far haven’t found a straightforward way to write an xattr value.

TIA.

-Chris

I’ve never found a straightforward method. Instead, for a script that I use to add extended attributes to old WordPerfect files, I used the hex string of the text of the attribute that I found in other files that already had the correct attribute.

Here is the routine I use, which is far more elaborate than you need, because it first tests the file to determine which version of WordPerfect created the file so that it can apply the correct attribute, but you’ll get the idea. The only line you really need is the one that runs a shell script with xattr. It’s possible that all you need is the string that begins com.agileTortoise, etc, and not any hex string.

The code is incompetent because I don’t know how to write anything better, unfortunately, but it seems to work.

on setAttr(wpf, wpfPath, folderProcess)
	
	try
		set hasHeader to ((read wpf for 4 as data) is «data rdatFF575043»)
		if hasHeader is true then
			
			set fixDocument to false
			set fileTypeByte to (read wpf from 10 for 1 as data)
			set versionByte to (read wpf from 11 for 1 as data)
			--if not fileTypeByte is «data rdat16» then -- not WP Graphic
			if (fileTypeByte is «data rdat2C») then -- WPMac
				set fixDocument to true
				if (versionByte is «data rdat02») then -- Mac WP 2.1
					set hexString to "5750443257504332000000000000000000000000000000007400000000000000"
				else if (versionByte is «data rdat03») then -- Mac WP 3.x
					set hexString to "5750443357504332000000000000000000000000000000007400000000000000"
				else if (versionByte is «data rdat04») then -- Mac WP 3.5e
					set hexString to "5750443457504332000000000000000000000000000000006E74000000000000"
				else -- use WP5 for anything else
					set hexString to "2E57503557504332010000000000000000000000000000000000000000000000"
				end if
			else if (fileTypeByte is «data rdat0A») then -- WPDOS
				set fixDocument to true
				if (versionByte is «data rdat00») or (versionByte is «data rdat02») or (versionByte is «data rdat03») or (versionByte is «data rdat04») or (versionByte is «data rdat0A») or (versionByte is «data rdat2C») then
					if (versionByte is «data rdat00») then -- WP5.x 
						set hexString to "2E57503557504332010000000000000000000000000000000000000000000000"
					else -- WPDOS 6+ and miscellaneous others
						set hexString to "2E57503657504332000000000000000000000000000000000000000000000000"
					end if
				end if
			end if
			
			if fixDocument is true then
				try
					do shell script "xattr -w -x com.apple.FinderInfo" & space & hexString & space & quoted form of wpfPath
					
					-- set end of fixedList to wpfPath
					set end of fixedList to "a"
					
					tell application "System Events"
						try
							set fileKind to kind of wpf
							if fileKind does not contain "Word Perfect fics" then
								if fileKind does not contain "WordPerfect" then
									if name of wpf is not in noProcessList then
										
										set noMsgShow to my badFileMsg(wpf, wpfPath, folderProcess, noMsgShow)
										
									end if
								end if
							end if
						end try
					end tell
				on error err
					if err does not contain "hexString" then
						activate
						display dialog err
					end if
				end try
			end if
			--end if
		end if
	end try
	
end setAttr
1 Like

This project seems useful if we can build.
Intel x64 binary seems to exist. I got x64 binary by using brew command.

1 Like

Thanks to @emendelson and @Piyomaru.

This shell script assigns the given file a default app of Drafts.app:

xattr -w -x com.apple.LaunchServices.OpenWith '62706C69 73743030 D3010203 04050657 76657273 696F6E54 70617468 5F101062 756E646C 65696465 6E746966 69657210 005F1018 2F417070 6C696361 74696F6E 732F4472 61667473 2E617070 5F101C63 6F6D2E61 67696C65 746F7274 6F697365 2E447261 6674732D 4F535808 0F171C2F 314C0000 00000000 01010000 00000000 00070000 00000000 00000000 00000000 006B' ~/Downloads/test-xattr.txt

It ain’t pretty, but it works well enough and is way better than having to do the job via the macOS UI.


  • Change the default-app of an applicable file to the desired app manually.
  • Read the OpenWith hex string using:
    • xattr -px com.apple.LaunchServices.OpenWith ~/path-to-file
  • Compose an xattr command similar to the one above using the hex string.

Hi @ccstone,

Very interesting! I could use this in a couple of my scripts generating PDFs which I prefer to open in Preview instead of Acrobat, the default on my system (Monterey 12.6.3).

Your code is working well here but returns a quarantine error at the second attempt to open the file.
I managed this issue by deleting the quarantine attribute:

set aPath to "some path"
set theAttr to "62706C6973743030D30102030405065776657273696F6E54706174685F101062756E646C656964656E74696669657210005F10202F53797374656D2F4170706C69636174696F6E732F507265766965772E6170705F1011636F6D2E6170706C652E50726576696577080F171C2F31540000000000000101000000000000000700000000000000000000000000000068"
do shell script "xattr -w -x com.apple.LaunchServices.OpenWith " & quoted form of theAttr & space & quoted form of aPath
do shell script "xattr -w -x 'com.apple.quarantine' nil " & quoted form of aPath

But a problem remains: the Finder information window for the file will not reflect the change until you restart of the system or the Finder.

Can anyone give us a solution to update this information?

This is not happening on my macOS 10.14.6 Mojave system.

It’s really weird that the error occurs on the second attempt to open the file.

This too is not happening on my macOS 10.14.6 Mojave system.

Sounds like Apple has introduced a few new bugs…

You might try simply deleting the quarantine bit:

do shell script "xattr -d 'com.apple.quarantine <pathToFile>

Deleting the resource does not prevent the error from reappearing. You have to set it to nil:

do shell script "xattr -w -x 'com.apple.quarantine' nil " & quoted form of aPath

Regarding the Finder info window issue, I found a workaround: I add a tag to the file then delete it.

1 Like