Краткий запуск приложений Mac OS из командной строки

apple.stackexchange https://apple.stackexchange.com/questions/4240

Вопрос

Я выполняю достаточную работу в командной строке, и я определяю множество псевдонимов формы:

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

Есть ли способ добавить магию таким образом, чтобы запрашивать исполняемый «foo» автоматически использует исполняемые/апппликации/foo.app/contents/macos/foo? Это на OS X 10.6.

(Я знаю, что могу сделать open foo.pdf, но Skim не является чтением PDF по умолчанию, и я бы хотел общее решение - в некоторых случаях не подходит для установления рассматриваемого приложения в качестве обработчика по умолчанию для файла.)

Это было полезно?

Решение

Наконец -то я понял: добавьте это в свой .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()

Теперь следующая работа:

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

Редактировать Рейд:

Я реализовал приведенный выше как сценарий Python, который делает сценарии обертки вместо псевдонимов. Вам нужно будет положить ~/bin/mankoffmagic на вашем пути. Если вы хотите, чтобы обертки обновлялись автоматически, регулярно запускайте его из Cron или 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()

Другие советы

Вам не нужно ничего необычного, у вас уже есть ответ. Пытаться:

open /Applications/Foo.app bar.pdf

на редактирование

В свете комментариев ниже, я думаю, что мой ответ все равно будет относительно похожим ... Я бы сделал функцию, которая переопределяется, делает толчок к /Applications, звонки /usr/bin/open $appName.app $args, делает POPD и возвращается.

Я отстой в сценарии Shell, но что -то вроде ниже, которое охватывает особые случаи и держит вас в целом, почти тот же синтаксис, что и Apple, предоставляя открытый. Мне нравится держать окружающую среду максимально чистой.

Я уверен, что синтаксис из космоса:

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
}

На втором редактировании

Глядя на комментарий @Mankoff по первоначальному вопросу, большинство вещей в вышеупомянутой функции, вероятно, было бы пустой тратой времени, так как вы могли бы просто использовать open -a $appName. Анкет Таким образом, у Мэнкоффа, вероятно, самое простое решение и должен изменить свой комментарий на ответ;)

Есть два решения, о которых я могу подумать:

Более простой способ - С использованием Info.plist файл в каждом .app Contents каталог, создайте индекс значения для ключей cfbundleexecutable. Затем добавьте короткий псевдоним, который вызывает сценарий (Perl, Python, что угодно) с именем исполняемого и аргументами, которые вы хотели бы пройти.

Ваш индекс будет пары исполняемых имен и путей к этим исполняемым файлам. Вам придется написать повторяющийся запланированный сценарий, чтобы сохранить его обновленным.

В конечном итоге вы сможете позвонить:

f foo file.txt

где F - псевдоним для скрипта, который проверяет ваш индекс на предмет исполняемого файла foo.

В общем, не так много работы, чтобы получить функциональность, которая вам нужна.

Более сложный путь - расширить свою оболочку, чтобы дополнить обработку его command_not_found ошибка. По сути вы бы внедрили рубиновый стиль method_missing функциональность в любой оболочке, которую вы используете. Когда command_not_found был брошен, ваш метод проверил бы исполняемые имена ваших установленных приложений.

AppleScript на помощь:

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

Замените имя приложения на приложение, которое вы хотите начать, и все готово. Вы, конечно, можете сделать это функцией оболочки, если это необходимо:

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

и используйте это таким образом:

f iTunes

Я ненавижу AppleScript, но иногда это полезно, и я считаю, что единственный способ обратиться к приложению просто по имени в командной строке. Все остальное потребует полный путь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с apple.stackexchange
scroll top