Finally I got it:
Add this to your .bash_profile
function foomagick() {
rm -f ~/.foomagick.tmp
ls /Applications/ | grep "\.app" | grep -v iWork | while read APP; do
# clean it up
a=`echo $APP | sed s/\ //g`;
a=`echo $a | sed s/\'//g`;
echo alias ${a%.*}="'open -a \"${APP%.*}\"'" >> ~/.foomagick.tmp
done
source ~/.foomagick.tmp
rm ~/.foomagick.tmp
}
foomagick()
Now the following work:
Skim # open Skim.app
Skim foo.pdf
FireFox http://google.com
FireFox google.com # ERROR. Looks for local file.
Edit by Reid:
I implemented the above as a Python script that makes wrapper scripts instead of aliases. You will need to put ~/bin/mankoffmagic
in your path. If you want the wrappers to be updated automatically, run it regularly from cron or somesuch.
#!/usr/bin/python
#
# This script automagically updates a set of wrapper shell scripts in
# ~/bin/mankoffmagic which call Mac apps installed in /Applications.
#
# Inspired by mankoff's shell alias posted on apple.stackexchange.com; see:
# http://apple.stackexchange.com/questions/4240/concisely-starting-mac-os-apps-from-the-command-line/4257#4257
#
# Notes/Bugs:
#
# 1. Does not follow symlinks (aliases?)
#
# 2. Assumes that application names do not contain double-quotes.
#
# 3. Not very smart about finding the actual binary (it guesses). This is
# wrong sometimes, e.g. Firefox. Probably a deeper understanding of the app
# package structure would fix this.
import copy
import glob
import os
import os.path
import re
BINDIR = os.path.expandvars("$HOME/bin/mankoffmagic")
APP_RE = re.compile(r'(.*)\.app$')
STRIP_RE = re.compile(r'[\W_]+')
def main():
# We aggressively delete everything already in BINDIR, to save the trouble
# of analyzing what should stay
for f in glob.glob("%s/*" % BINDIR):
os.unlink(f)
# Walk /Applications and create a wrapper shell script for each .app dir
for (root, dirs, files) in os.walk("/Applications"):
dirs_real = copy.copy(dirs) # so we can manipulate dirs while looping
for d in dirs_real:
#print "checking %s" % os.path.join(root, d)
m = APP_RE.search(d)
if (m is not None):
#print "Found " + m.group()
dirs.remove(d) # no need to recurse into app
create_script(root, d, m.group(1))
def create_script(path, appdir, appname):
# remove non-alphanumerics and downcase it
wrapper = STRIP_RE.sub('', appname).lower()
wrapper = os.path.join(BINDIR, wrapper)
fp = open(wrapper, "w")
# Twiddle the comments in the script depending on whether you want to
# invoke the binary or use "open" -- the former lets you use any
# command-line args, while the latter is more Mac-like (app puts itself in
# the front, etc.)
fp.write("""
#!/bin/sh
exec "%s/%s/Contents/MacOS/%s" "$@"
#open -a "%s" "$@"
""" % (path, appdir, appname, appname))
fp.close()
os.chmod(wrapper, 0700)
if (__name__ == "__main__"):
main()
While not (strictly speaking) playing from the command line, you could use a set of AppleScripts (or AppleScript calls) wrapped in shell scripts to control a GUI player or website. In the likely case that the player or site doesn't directly support AppleScriptability, you can use AppleScript GUI scripting to control the mouse and keyboard.
If you're looking at a "normal" streaming radio station (i.e, one that has a downloadable file that specifies the stream), you can put that in iTunes and use its (relatively excellent) AppleScript dictionary to remotely control it.
With either option, if you want to get fancy, you can use remote scripting to send Apple Events from an arbitrary source machine to control your radio-iMac.
Best Answer
Yes! The OS X Chess app relies on the sjeng engine, which has a command line version. Type
/Applications/Chess.app/Contents/Resources/sjeng.ChessEngine
and press enter to play:Make moves with the coordinates of the origin and destination you want:
e1e4
moves the piece at e1 to e4.Sjeng doesn't take any command line arguments, but you can edit the config file (stored in
/Applications/Chess.app/Contents/Resources/sjeng.rc
). This will probably mess with your settings in the GUI Chess app; make a backup before editing.