コマンドラインからMac OSアプリを簡潔に起動する


22

コマンドラインでかなりの量の作業を行いますが、次の形式のエイリアスを多数定義しています。

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

実行可能ファイル "foo"を要求すると、実行可能ファイル/Applications/Foo.app/Contents/MacOS/Fooが自動的に使用されるように魔法を追加する方法はありますか?これはOS X 10.6にあります。

(私はできることを知ってopen foo.pdfいますが、SkimはデフォルトのPDFリーダーではありません。一般的なソリューションが欲しいです-場合によっては、問題のアプリケーションをファイルのデフォルトハンドラとして設定するのは適切ではありません)


22
できopen -a Skim foo.pdfます。

1
@mankoff:いいですね、-aを使用して、アプリケーションディレクトリからアプリが必要であることをopenに伝えることができなかったことを忘れました。これを回答に変更する必要があります:)
ロバートSチャシオ

@Reid:質問を編集して、入力可能なコマンドラインの例を含めることができますか?
ロバートSチャシオ

@mankoffは、タブ補完の確実なまたは拡張のためにエイリアスが必要であることを意味します
ロバートSチャシオ

@ソリューションに問題がありますか?

回答:


10

最後に私はそれを手に入れました:これをあなたの .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()

「iWork '09」のアポストロフィが混乱しているという理由だけで、「grep -v iWork」がそこにあります。アプリを他の場所(〜/ local / Applications)に保存する場合は、lsコマンドに追加するだけで、これもそこで機能します。

良いですね。私はそれが動的であることが好きなので、古いエイリアスをクリーンアップするなどのメンテナンスの問題で終わることはありません。
ロバートSチャシオ

ありがとう@mankoff!素晴らしい匂い-それをテストし、それが動作したら、答えを受け入れたとマークします。とても有難い。
リード

OK、これは動作します。アポストロフィ(およびおそらく名前に含まれる他の面白い文字)を持つアプリでは機能しません。私はあなたの解決策をリフし、Pythonで似たようなことをしました。別の答えを投稿します-それが適切なエチケットでない場合は、代わりに(または何でも)あなたの答えに追加させていただきます。
リード

8

派手なものは必要ありません。すでに答えがあります。試してください:

open /Applications/Foo.app bar.pdf

編集中

以下のコメントに照らして、私の答えはまだ比較的似ていると思います... openをオーバーライドし、pushd toを実行し/Applications、calls /usr/bin/open $appName.app $argsを実行し、popdを実行してリターンする関数を作成します。

私はシェルスクリプトを嫌いますが、以下のような特別なケースをカバーし、オープン用に提供されたアップルとほぼ同じ構文を使用し続けます。私は自分の環境を可能な限りきれいに保つのが好きです。

私は構文が宇宙からのものであると確信しています:

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。そのため、mankoffはおそらく最も簡単な解決策を持っているので、彼のコメントを回答に変更する必要があります;)


@Reidは、すべてのエイリアスを手動で作成しない短い方法を望んでいると思います。

ただし、.appパッケージで 'open'を使用する場合、unix実行可能ファイルのエイリアスを作成する必要はありません。コマンドラインから直接アプリを起動する唯一の方法は、MacOSディレクトリに移動して、アプリ内で「実際の」実行可能ファイルを実行することだと考えたため、エイリアスを作成しているという印象を受けました。したがって、その場合、エイリアスを使用すると、アプリを起動するために必要な追加の3レベルのディレクトリ構造を入力する必要がなくなります。たぶん私は彼の質問を誤解しています。
ロバートSチャシオ

@calevara、ありがとう-@mankoffは正しい。それは長さについてです。
リード

3
これは、編集機能の誤用です。後で2番目の答えを提案したい場合は、それを実行してください。元の回答を編集しないでください。受け取った票を新しいアイデアに便乗させてください。
ジェフスウェンセン

1
私は同意しません...彼は同じ構文を使用しているので、答えはまだかなり似ています。それだけでなく、投票者が新しい回答を好まない場合は、回答が編集されているため投票を変更できます。それがまさに、編集後に投票を変更できる理由です。また、「編集中」を太字にした理由でもあります。
ロバートSチャシオ

4

私が考えることができる2つの解決策があります:

より簡単な方法 - Info.plist各.app Contentsディレクトリのファイルを使用して、キーCFBundleExecutableの値のインデックスを作成します。次に、実行可能ファイルの名前と渡したい引数でスクリプト(perl、pythonなど)を呼び出す短いエイリアスを追加します。

インデックスは、実行可能ファイル名とそれらの実行可能ファイルへのパスのペアになります。これを最新の状態に保つには、定期的なスケジュールスクリプトを作成する必要があります。

あなたは電話をかけることができるようになります:

f foo file.txt

fは、という名前の実行可能ファイルのインデックスをチェックするスクリプトのエイリアスfooです。

全体として、必要な機能を得るための多くの作業はありません。

より難しい方法 - command_not_foundエラーの処理を補完するためにシェルを拡張します。基本的に、method_missing使用しているシェルにRubyスタイルの機能を実装します。ときにcommand_not_foundスローされた、あなたの方法は、インストールしたアプリケーションの実行ファイル名を確認します。


2

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が嫌いですが、それはときどき役に立ちます。コマンドラインで名前だけでアプリケーションをアドレス指定する唯一の方法だと思います。それ以外はすべて完全なパスが必要です。


タブ補完をサポートしていません。アプリ名を正確に覚えておく必要があります。AppleScriptが必要な理由がわからない(特に嫌いな場合)シェルスクリプトがすべてを実行できる場合。

1
引数としてファイル名なしでopen -aを使用できることに気づきませんでした。そして、私はNextStepから90年代前半に時々openを使用しています!私がそれに投票できるように、それを回答として提出してください。そうです、正解は「オープン-a <アプリケーション名>」使用することです
エリック・
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.