Concisely beginning Mac OS applications from the command line

I do a reasonable quantity of operate in the command line, and also I locate myself specifying a great deal of pen names of the kind:

alias skim='/Applications/Skim.app/Contents/MacOS/Skim'

Is there a means to add magic such that requesting for executable "foo" instantly makes use of executable/ Applications/Foo. app/Contents/MacOS/ Foo? This gets on OS X 10.6.

(I'm mindful that I can do open foo.pdf, yet Skim is not the default PDF viewers, and also I would certainly such as a basic remedy - in many cases, it is not ideal to set the application concerned as the default trainer for the documents.)

0
2019-05-13 04:25:28
Source Share
Answers: 4

There are 2 remedies that I can consider:

The less complicated means - Using the Info.plist documents in each.app Contents directory site, create an index of the value for the keys CFBundleExecutable. After that add a brief pen names that calls a script (perl, python, whatever) with the name of an executable and also the debates you would certainly such as to pass.

Your index would certainly be sets of executable names and also courses to those executables. You would certainly need to write a reoccuring set up script to maintain this upgraded.

You would certainly wind up having the ability to call:

f foo file.txt

where f is a pen name to a script that examines your index for an executable called foo.

In conclusion, not a great deal of job to get the capability you would certainly such as.

The tougher means - Extend your covering to supplement the handling of its command_not_found mistake. Basically you would certainly implement a Ruby design method_missing capability within whatever covering you are making use of. When command_not_found was tossed, your method would certainly examine the executable names of your mounted Applications.

0
2019-05-17 17:13:47
Source

Applescript to the rescue:

osascript -e 'tell application "iTunes"' -e "activate" -e 'end tell'

Replace the name of the application with the application you intend to start and also you are done. You can certainly make it a covering function if required:

function f() {
    osascript <<EOF
tell application "$1"
  activate
end tell
EOF
}

and also utilize it in this way:

f iTunes

I despise applescript, yet it serves occasionally, and also I think the only means to resolve an application merely by name on the command line. Every little thing else will certainly call for a complete course.

0
2019-05-17 16:41:34
Source

Finally I obtained 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 adhering to job:

Skim # open Skim.app
Skim foo.pdf
FireFox http://google.com
FireFox google.com # ERROR. Looks for local file.

Edit by Reid:

I applied the above as a Python script that makes wrapper manuscripts as opposed to pen names. You will certainly require to place ~/bin/mankoffmagic in your course. If you desire the wrappers to be upgraded instantly, run it consistently 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" "[email protected]"
#open -a "%s" "[email protected]"
""" % (path, appdir, appname, appname))
   fp.close()
   os.chmod(wrapper, 0700)


if (__name__ == "__main__"):
   main()
0
2019-05-17 16:14:09
Source

You do not require anything expensive, you currently have the solution. Attempt:

open /Applications/Foo.app bar.pdf

on edit

In light of the remarks listed below, I assume my solution would certainly still be reasonably comparable ... I would certainly make a function that bypasses open, does a pushd to /Applications, calls /usr/bin/open $appName.app $args, does a popd and also returns.

I draw at covering scripting yet something like listed below which covers grandfather clauses and also maintains you making use of virtually the very same syntax as apple attended to open. I such as to maintain my setting as tidy as feasible.

I'm certain the syntax is from celestial spaces:

function open($appName, $args)
{
    #if we are calling open without a path like /Applications/TextEdit.app AND
    #    $appName ends in '.app'
    if (!hasParent($appName) && isApp($appName))
    {
        pushd /Applications
        /usr/bin/open ${appName}.app $args &
        popd
        return
    }
    #otherwise, use open as normal
    /usr/bin/open $appName $args
    return
}

on 2nd edit

looking @mankoff is talk about the initial inquiry, a lot of right stuff in the above function would possibly be a wild-goose chase given that you can simply make use of open -a $appName. So mankoff possibly has the most convenient remedy and also needs to transform his comment to a solution ;)

0
2019-05-17 16:05:48
Source