Shell Script in An OSX Bundle And More
Dr. Ping Yeh brought up a question about how to put a shell script in the Dock of Mac OS X. My original thought about this question is to solve it with a shell script with a file extension/type *.command and it can be run by double clicking it. Open the *.command files and the Terminal.app will launch the shell to run it. But the problem becomes the limitation of the left side of the Dock, a item has to be an "application" to sit in the left side of the Dock. (At the time we didn't work it thoroughly and forgot the right side the Dock... The thing is, you can just put the *.command file in the right side of the separator and click to launch it.)
You have to wrap your shell script into an application if you want it to stay in the left side of the Dock. Luckily we can follow the procedure in this document by Artem Fishman (via google search).
Basically the bundle structure looks like this:
Basically the bundle structure looks like this:
MyBundle.app MyBundle.app/Contents MyBundle.app/Contents/Info.plist MyBundle.app/Contents/MacOS MyBundle.app/Contents/MacOS/MyBundle MyBundle.app/Contents/MacOS/startup.command MyBundle.app/Contents/Resources MyBundle.app/Contents/Resources/MyIcons.icns(The name "MyIcons" is defined in Info.plist file.)
However that document only helps you run the script silently. It's not enough if you want to be able to read the output of the shell script or even interact with the shell script. A better way to do it is just simply writing your main script in a command file inside the bundle and "open" the command like this:
#!/bin/sh #File: MyBundle.app/Contents/MacOS/MyBundle mypath=`dirname "$0"` open $mypath/starup.commandWith this command file:
#!/bin/sh #File: MyBundle.app/Contents/MacOS/startup.command echo "this is a test" /bin/sleep 5This will give a terminal window with the output of "this is a test" and 5 seconds delay. Now you have a working application that can be put on the dock and also give you an opportunity to read the output!
Unfortunately this new application doesn't close the terminal window automatically. You got a "Completed Command" window after the application finished and it requires you to close it manually. This had been my major quest since the first time I knew about the *.command files. I always want to improve a program called VMD, a program that shells-out a console window but leaves that window half dead after finished all the task. This time I decided to finish this quest. I started with closing the window in the front or idle window with Applescript but the side-effects are bad --- either logically bad or bugs on Terminal.app . Later I have to abandon the idea of using "open" command asking Terminal.app to open the script.
Yay! Eventually I did it.
(Update: This demo bundle is now available for download.)#!/bin/sh #File: MyBundle.app/Contents/MacOS/MyBundle mypath=`dirname "$0"` osascript << EOT tell application "System Events" to set terminalOn to (exists process "Terminal") tell application "Terminal" if (terminalOn) then activate do script "\"$mypath/startup.command\"; exit" else do script "\"$mypath/startup.command\"; exit" in front window end if end tell EOT exit 0Time to fix the VMD.
(Update: It turns out that if you already have Terminal.app running, clicking the command files on right side of the dock might not be working.)
(Update: In order to make the trick work, you still need to set your terminal.app's shell preference to "close only if the shell exited cleanly".)
(Update: For processing arguments and drop actions, use the DropScript by Wilfredo Sánchez, updated source can be found through SVN repository. Also checkout his introduction.)
(Update: Some shell scripts are suitable for contextual menu items. Check the website out.)
2 comments:
Hi MJ,
how are you guys? Have you tried to put freebsd on an intel-mac?
regards,
TFC
Why would I do this kind of thing? No, I probably won't try that. If I ever want to try it, I would run it on vmware.
Post a Comment