How can I change the default app for all files of a particular file type through the Terminal in OS X?

link|improve this question
Not a dupe, even though I kind of answered it there. Sorry about that. – Daniel Beck Apr 21 '11 at 17:25
For power use, I like the accepted answer under a more recent Super User question, Is there a faster way to change default apps associated with file types on OS X?. For simplicity, I like Daniel's answer below. – Graham Perrin Apr 29 at 13:08
feedback

1 Answer

Edit ~/Library/Preferences/com.apple.LaunchServices.plist.

Add an entry under LSHandlers, containing the UTI (key LSHandlerContentType, e.g. public.plain-text) and application bundle identifier (LSHandlerRoleAll, e.g. com.macromates.textmate).

It looks like this in Property List Editor:

alt text alt text

To do this from the command line, use defaults or /usr/libexec/PlistBuddy. Both have extensive manpages.

For example to open all .plist files using Xcode:

defaults write com.apple.LaunchServices LSHandlers -array-add '{ LSHandlerContentType = "com.apple.property-list"; LSHandlerRoleAll = "com.apple.dt.xcode"; }'

Of course, you'd need to make sure there's not already another entry for the UTI com.apple.property-list already in there.

Here's a more complete script that'll remove existing entries for a UTI and add a new one. It can only handle LSHandlerContentType, and will always set LSHandlerRoleAll, and has hard-coded bundle IDs instead of parameters. Other than that, it should work quite well.

#!/usr/bin/env bash

PLIST="$HOME/Library/Preferences/com.apple.LaunchServices.plist"
BUDDY=/usr/libexec/PlistBuddy

# the key to match with the desired value
KEY=LSHandlerContentType

# the value for which we'll replace the handler
VALUE=public.plain-text

# the new handler for all roles
HANDLER=com.macromates.TextMate

$BUDDY -c 'Print "LSHandlers"' $PLIST >/dev/null 2>&1
ret=$?
if [[ $ret -ne 0 ]] ; then
        echo "There is no LSHandlers entry in $PLIST" >&2
        exit 1
fi

function create_entry {
        $BUDDY -c "Add LSHandlers:$I dict" $PLIST
        $BUDDY -c "Add LSHandlers:$I:$KEY string $VALUE" $PLIST
        $BUDDY -c "Add LSHandlers:$I:LSHandlerRoleAll string $HANDLER" $PLIST
}

declare -i I=0
while [ true ] ; do
        $BUDDY -c "Print LSHandlers:$I" $PLIST >/dev/null 2>&1
        [[ $? -eq 0 ]] || { echo "Finished, no $VALUE found, setting it to $HANDLER" ; create_entry ; exit ; }

        OUT="$( $BUDDY -c "Print 'LSHandlers:$I:$KEY'" $PLIST 2>/dev/null )"
        if [[ $? -ne 0 ]] ; then 
                I=$I+1
                continue
        fi

        CONTENT=$( echo "$OUT" )
        if [[ $CONTENT = $VALUE ]] ; then
                echo "Replacing $CONTENT handler with $HANDLER"
                $BUDDY -c "Delete 'LSHandlers:$I'" $PLIST
                create_entry
                exit
        else
                I=$I+1 
        fi
done
link|improve this answer
1  
The easiest way is probably to x=~/Library/Preferences/com.apple.LaunchServices.plist; plutil -convert xml1 $x; open -a TextEdit $x and copy and paste those LSHandlers entries. To get the bundle identifier you can do osascript -e 'bundle identifier of (info for (path to app "TextEdit"))'. – Lri Apr 22 '11 at 6:24
@Lri In a way, yes, but this question is specifically about the command line. I figured that TextEdit (or Property List Editor / Xcode) doesn't qualify; I just copied over that part with Property List Editor from my other answer for illustration purposes. Useful remark on the bundle identifier. – Daniel Beck Apr 22 '11 at 8:40
Credit to Daniel, I borrowed from this for an answer to a question in Ask Different, Can Finder and the “open” command treat files with .sh or other typical extensions just like .command files?. – Graham Perrin Apr 29 at 13:11
If there does exist an alternative entry for the UTI, would you agree that "command line removal of a single dictionary from an array may be unnecessarily difficult"? – Graham Perrin Apr 29 at 13:14
1  
@GrahamPerrin It is unnecessarily difficult because defaults doesn't seem to be capable to do it, and it requires a few PlistBuddy calls. But it's possible to do it in a reusable shell script. – Daniel Beck Apr 29 at 18:58
show 1 more comment
feedback

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.