Я довольно много работаю в командной строке и обнаруживаю, что определяю множество псевдонимов вида:
alias skim='/Applications/Skim.app/Contents/MacOS/Skim'
Есть ли способ добавить магию, чтобы при запросе исполняемого файла «foo» автоматически использовался исполняемый файл /Applications/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 или чего-то подобного.
#!/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()
ls
команду, и это тоже будет работать там.Вам не нужно ничего необычного, у вас уже есть ответ. Пытаться:
open /Applications/Foo.app bar.pdf
В свете комментариев ниже, я думаю, что мой ответ все равно будет относительно похожим... Я бы сделал функцию, которая переопределяет open, выполняет pushd to /Applications
, вызывает /usr/bin/open $appName.app $args
, делает popd и возвращает.
Я плохо разбираюсь в сценариях оболочки, но что-то вроде ниже, которое охватывает особые случаи и заставляет вас использовать почти тот же синтаксис, что и Apple, предоставленный для open. Мне нравится, чтобы мое окружение было как можно более чистым.
Я уверен, что синтаксис из космоса:
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
. Так что у манкоффа, вероятно, самое простое решение, и он должен изменить свой комментарий на ответ;)
$ foo bar.pdf
?Есть два решения, которые я могу придумать:
Более простой способ — используя Info.plist
файл в каждом каталоге .app Contents
, создайте индекс значения для ключей CFBundleExecutable. Затем добавьте короткий псевдоним, который вызывает скрипт (perl, python, что угодно) с именем исполняемого файла и аргументами, которые вы хотите передать.
Ваш индекс будет состоять из пар имен исполняемых файлов и путей к этим исполняемым файлам. Вам нужно будет написать повторяющийся запланированный сценарий, чтобы обновлять его.
В конечном итоге вы сможете позвонить:
f foo file.txt
где f — это псевдоним скрипта, который проверяет ваш индекс на наличие исполняемого файла с именем foo
.
В общем, не так много работы, чтобы получить желаемую функциональность.
Более сложный способ - расширить свою оболочку, чтобы дополнить обработку ее command_not_found
ошибок. По сути, вы должны реализовать функциональность в стиле Ruby 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, но иногда он полезен, и я считаю, что единственный способ обратиться к приложению просто по имени в командной строке. Для всего остального потребуется полный путь.
пользователь588
open -a Skim foo.pdf
.Роберт Чаччо
Роберт Чаччо
Роберт Чаччо
пользователь588