This is doable, but probably isn't as straightforward as you might think. You'll need to get very familiar with Uniform Type Identifiers. Look at Wikipedia's Uniform Type Identifier page.
OS X stores information on preferred file associations in a preference file with the name com.apple.LaunchServices.plist
. Before you go try to find and modify that file, I suggest you familiarize yourself with OS X's domain hierarchy for defaults (a.k.a. "settings"). A decent article on this can be found here. (Disclaimer: they seem to be selling something on that site. I don't know what it is and have no association with them, the explanation is just a good one.)
Now that you know all about defaults and UTIs (er, not the medical kind), now we can talk about setting file associations from a script/command line.
First, you'll need to know the proper way to identify the files for which you want to make an association.
Remember how I said UTIs were important? There are multiple ways to identify a file. It depends on if the type has been formally declared on your system or not. For example, decent text editors like TextMate or TextWrangler will add quite a few type declarations to the type hierarchy when you use them on your system. If, however, you don't have those applications, you may not have those types declared.
OK, enough talk. Examples:
Get the UTI for a file:
$ mdls myFile.xml
...
kMDItemContentType = "public.xml"
kMDItemContentTypeTree = (
"public.xml",
"public.text",
"public.data",
"public.item",
"public.content"
)
...
Ok, cool. An explicit content type we can use. Write that down somewhere.
$ mdls myFile.myExtn
...
kMDItemContentType = "dyn.ah62d4rv4ge8048pftb4g6"
kMDItemContentTypeTree = (
"public.data",
"public.item"
)
...
Oops. OS X doesn't know about ".myExtn" files. So, it created a dynamic UTI that we can't use for anything. And the parent types are too generic to be useful.
Now that we know what our files are, lets look at the LaunchServices.plist file and see what we can do:
$defaults read com.apple.LaunchServices
{
...
LSHandlers = (
{
LSHandlerContentType = "public.html";
LSHandlerRoleAll = "com.apple.safari";
LSHandlerRoleViewer = "com.google.chrome";
},
...
{
LSHandlerContentTag = myExtn;
LSHandlerContentTagClass = "public.filename-extension";
LSHandlerRoleAll = "com.macromates.textmate";
},
...
);
...
}
So, when you have a "good" content type to use, the first construct is better. Otherwise the other construct. Note, there are other constructs in that file, but they aren't relevant to what you asked. Just know they are there when you look through the output.
As you can see, you'll need to find the UTI for the application you want to use. The UTIs for Safar and TextMate are in my example above, but to generically find the UTI for an application:
$ cd /Applications/MyApp.app/Contents
$ less Info.plist
...
<key>CFBundleIdentifier</key>
<string>com.apple.Safari</string>
...
NOTE: I have no idea what constitutes the difference between LSHandlerRoleAll and LSHandlerRoleViewer. I can't find documentation on that anywhere. What I do see is that 99% of the time LSHandlerRoleAll is the only one set (i.e. there is no LSHandlerRoleViewer at all) and that it is set to the UTI for the application that you desire to associate the type with.
Having brought you this far, I'm going to leave HOW to set the values you want as an exercise for the reader. Messing with these things can be somewhat dangerous. It is entirely possible for you to screw up a file and not have ANY of your file associations work. Then you have to throw away the file and start over.
Some hints:
- Read up on
defaults write
and its syntax
- Take a look at
PlistBuddy
. man PlistBuddy
and /usr/libexec/PlistBuddy -h
- Skip all this nonsense altogether and use RCDefaultApp
Updated Answer:
The code below it what I'd use to replace the original code offered as there appears to be a bug in AppleScript when using the do shell script
command in the manner originally presented that isn't present went the code, in a representative manner, is run in a bash
script in Terminal.
Note that anytimeopen for access
is used, it needs to be coded to trap any errors and try and close the file, which this attempts to do. That said it is not necessarily then only error handling I'd employ and all coding answer I present are done so as proof of concept and the onus to write code employing reasonable error handing is yours to fulfill.
As coded, this will create the target file if it doesn't exist while adding the text to add to it and if it does exist, places the text to add as the top line of the target file.
set targetFilePathname to (POSIX path of (path to desktop as string) & "My Fruit Log.txt")
-- # set theTextToWrite to "This text will be written at the top of the file." & "\n"
set theTextToWrite to "This text will be written at the top of the file." & "\n"
set theOriginalText to ""
try
set theOriginalText to (read targetFilePathname) as string
end try
-- # set theTextToWrite to theTextToWrite & "\n" & theOriginalText
set theTextToWrite to theTextToWrite & "\n" & theOriginalText
try
set referenceNumber to open for access targetFilePathname with write permission
write theTextToWrite to referenceNumber starting at 0
close access referenceNumber
on error eStr number eNum
display dialog eStr & " number " & eNum buttons {"OK"} default button 1 with title "File I/O Error..." with icon caution
try
close access referenceNumber
end try
return
end try
Best Answer
You're close.
Get the path to your file by making a one-line script:
Copy the result of that. Then, in the script that will open the "Fallen_Order_Intro" script, tell the Finder to do the opening for you, pasting in your second script's path, obtained using the "choose file" script. Here's how it would look if your "Fallen_Order_Intro" script is on your desktop (and if your user name is sdavis).
That's all there is to it. The file will open in Script Editor because the Finder knows it's a Script Editor document.