명령 행에서 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를 사용하여 응용 프로그램 디렉토리에서 응용 프로그램을 원한다는 것을 알려주는 것을 잊었습니다. 당신은 이것을 답변으로 변경해야합니다 :)
Robert S Ciaccio

@Reid : 입력 할 수있는 예제 명령 줄을 포함하도록 질문을 편집 할 수 있습니까?
Robert S Ciaccio

@mankoff 그가 있는지 또는 탭 완성의 확장에 대한 별칭을 필요로하는 수단
로버트 S Ciaccio

@ 솔루션에 문제가 있습니까?

답변:


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()

"grep -v iWork"는 "iWork '09"의 아포스트로피가 엉망이되어 있기 때문입니다. 다른 곳에 (~ / local / Applications) 앱을 저장하면 ls명령에 추가 하면 작동합니다.

좋은 것. 동적이기 때문에 오래된 별칭 정리와 같은 유지 관리 문제가 발생하지 않습니다.
Robert S Ciaccio

감사합니다 @mankoff! 좋은 냄새가납니다. 일단 테스트를 해본 후 작동하면 답변을 표시하겠습니다. 매우 감사.
Reid

좋아, 이것은 작동한다. 아포스트로피 (아마도 이름에 다른 재미있는 문자)가있는 앱에서는 깨지지 않습니다. 나는 당신의 솔루션을 사용하고 파이썬에서 비슷한 일을했는데 다른 답변으로 게시 할 것입니다. 올바른 에티켓이 아니라면 대신 (또는 무엇이든) 귀하의 답변에 추가 해 드리겠습니다.
Reid

8

당신은 공상이 필요하지 않습니다, 당신은 이미 답을 가지고 있습니다. 시험:

open /Applications/Foo.app bar.pdf

편집 중

아래 의견에 비추어 볼 때, 내 대답은 여전히 ​​비교적이라고 생각합니다 ... 개방을 재정의하고, 푸시를 수행하고 /Applications, 호출하고 /usr/bin/open $appName.app $args, 팝을 수행하고 반환 하는 함수를 만들 것 입니다.

나는 쉘 스크립팅에 빠지지만 특별한 경우를 다루고 오픈을 위해 제공된 애플과 거의 동일한 구문을 사용하는 아래와 같은 것이 있습니다. 나는 가능한 한 환경을 깨끗하게 유지하고 싶다.

구문이 우주 공간에서 온 것 같습니다.

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'을 사용하는 경우 유닉스 실행 파일에 대한 별칭을 만들 필요가 없습니다. 명령 줄에서 직접 응용 프로그램을 시작하는 유일한 방법은 MacOS 디렉토리로 가서 응용 프로그램 내에서 '실제'실행 파일 인 파일을 실행하는 것이라고 생각했기 때문에 별칭을 만들고 있다는 인상을 받았습니다. 따라서이 경우 별칭은 앱을 시작하는 데 필요한 추가 3 단계의 디렉토리 구조를 입력하여 저장합니다. 어쩌면 나는 그의 질문을 오해하고 있을지도 모른다.
Robert S Ciaccio

@calevara, 감사합니다-@mankoff가 맞습니다. 그것은 길이에 관한 것입니다.
리드

3
이것은 편집 기능을 약간 잘못 사용하는 것입니다. 나중에 두 번째 답변을 제안하려면 그렇게하십시오. 원래의 답변을 편집하지 말고 새로운 아이디어에 대한 투표를 피기 백하십시오.
Jeff Swensen

1
동의하지 않습니다 ... 동일한 구문을 사용하고 있기 때문에 대답은 여전히 ​​유사합니다. 뿐만 아니라 유권자에게 새로운 답변이 마음에 들지 않으면 답변이 수정되어 투표를 변경할 수 있습니다. 이것이 바로 편집 후 투표를 변경할 수있는 이유입니다. 또한 "편집시"를 굵게 표시 한 이유도 있습니다.
Robert S Ciaccio

4

내가 생각할 수있는 두 가지 솔루션이 있습니다.

더 쉬운 방법 - 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가 필요한 이유 (특히 싫어하는 경우)를 보지 마십시오.

1
나는 파일 이름없이 open -a를 인수로 사용할 수 있다는 것을 결코 깨닫지 못했습니다. 그리고 나는 90 년대 초 때때로 NextStep 이후 오픈을 사용하고 있습니다! 투표 할 수 있도록 답변으로 제출하십시오. 정답은 'open -a <application name>'을 사용하는 것입니다.
eric
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.