LoginSignup
45
49

More than 5 years have passed since last update.

シェルスクリプトをアプリケーションバンドルにする方法

Last updated at Posted at 2013-11-04

MavericksのEmacsがおかしかったので調べていたら、シェルスクリプトをアプリケーションバンドルにする方法を学んでしまったので共有します。

なお、参考にしたのは以下のページの記述です。

いきさつ

(Mac )OS Xの上でのエディタとしてHomebrewで入れたEmacs.appを常用しています。そしてEmacs.appを起動して最初にやることはというとM-x diredなのですが、Mavericksからその挙動が若干変わっていることに気づきました。Mountain Lion上のEmacs.appではM-x diredするとミニバッファにDired (directory): ~/と出ます。ところが、Mavericks上のEmacs.appではDired (directory): /と出てしまうのです。scratchバッファで(pwd)したときの結果は"Directory /"となります。

もう少し調べていくとだいたい以下のようなことが分かりました。

起動方法 (pwd)したときの結果
DockからEmacs.appを起動 "Directory /"
open /Applications/Emacs.app "Directory /"
ターミナルから/Applications/Emacs.app/Content/MacOS/Emacs "Directory ~/"

どうやらopenやDock経由など、OS Xでアプリケーションバンドルを起動する標準的な方法で(つまり「普通に」)アプリケーションを起動するとカレントディレクトリが/になるようなのです。

では、OS Xで普通にアプリケーションを起動したときの環境変数は、どのようにして調べればいいのでしょう。これがシェルスクリプトをアプリケーションバンドルにする方法を調べるきっかけでした。

アプリケーションバンドルとは

アプリケーションバンドルとは、そのアプリケーションに関連するリソースをまとめたディレクトリで、(Mac )OS XおよびiOSのアプリケーションの標準形式です(なお、iOSの場合、アプリケーションバンドルをさらにzip形式でまとめて拡張子「.ipa」をつけた形でApp Storeなどで公開されています)。

シェルスクリプトのアプリケーションバンドル

実はシェルスクリプトをアプリケーションバンドルにすることは案外簡単にできます。必要なファイルは2つ、これらをルールにそって配置すれば、シェルスクリプトをアプリケーションであるかのようにすることが簡単にできるのです。

手順は以下の通りです。

  1. シェルスクリプトがアプリケーションバンドルになるようディレクトリを掘る。
  2. printenvの結果をテキストエディットで開くシェルスクリプトを書く。
  3. アプリケーションバンドルをローンチするとそのシェルスクリプトが動くようにする。

そこでアプリの名前を決めます。「Printenv(.app)」としましょう。

シェルスクリプトがアプリケーションバンドルになるようディレクトリを掘る

まずはPrintenv.appディレクトリを作成します。

mkdir ./Printenv.app

続いて、以下のようにディレクトリツリーをつくっていきます。

mkdir ./Printenv.app/Contents
mkdir ./Printenv.app/Contents/MacOS
mkdir ./Printenv.app/Contents/Resources

(もちろん、以下の手順のように一気に作成していくというのでも構いません)

mkdir -p ./Printenv.app/Contents/{MacOS,Resources}

printenvの結果をテキストエディットで開くシェルスクリプトを書く

次に、printenvの結果をテキストエディットで開くシェルスクリプトを書きますが、どこに書くかが大事です。

場所は./Printenv.app/Contents/MacOS内にします。シェルスクリプトの名前はアプリケーションの名前に合わせて(合わせなければいけないわけではありません。単に自分自身の分かりやすさのためです)、Printenv.shとします。

さて、2番めの手順を「printenvの結果をテキストエディットで開くシェルスクリプトを書く」としました。実は、標準出力からテキストエディットにテキストを流す、ということがOS Xではできます。それはopen -fコマンドです。man openによると、-fオプションは以下のように説明されています。

Reads input from standard input and opens the results in the default
text editor. End input by sending EOF character (type Control-D).
Also useful for piping output to open and having it open in the
default text editor.

デフォルトのエディタがテキストエディットであれば、printenvの結果をパイプでopen -fに流せば、あたかも環境変数一覧を表示するアプリであるかのようにprintenvの結果をテキストエディットで開くことができるのです。

そこで、以下のようなPrintenv.shを用意します。

./Printenv.app/Contents/MacOS/Printenv.sh
#!/bin/sh

/usr/bin/printenv | /usr/bin/open -f

(環境変数をそのまま出力したいのでPATH=...は書きません。その代わりprintenvopenはフルパスで指定します)

なお、このファイルには実行属性が必要です。chmod +xを実行しておきます。

chmod +x ./Printenv.app/Contents/MacOS/Printenv.sh

アプリケーションバンドルをローンチするとそのシェルスクリプトが動くようにする

最後に、アプリケーションバンドルをローンチするとそのシェルスクリプトが動くようにしますが、そのためには./Printenv.app/Contents/Info.plistというファイルを用意します。

./Printenv.app/Contents/Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>CFBundleExecutable</key>
    <string>Printenv.sh</string>
  </dict>
</plist>

キーCFBundleExecutableの値は(Info.plistから見て直下のサブディレクトリである)./MacOSディレクトリの中のファイルを書きます。そこで、./MacOS/Printenv.shではなく単にPrintenv.shと書きます。

実行する

出来上がると、Finderからは先ほどつくったPrintenv.appPrintenvというファイルであるように見えているはずです。

早速ダブルクリックしてみましょう。

結果はこのような感じです(一部伏せ字にしました)。

GPG_AGENT_INFO=/Users/h12o/.gnupg/S.gpg-agent:*****:1
SHELL=/bin/bash
TMPDIR=/var/folders/**/******************************/*/
Apple_PubSub_Socket_Render=/tmp/launch-******/Render
ANDROID_SDK_ROOT=/opt/android-sdk
USER=h12o
COMMAND_MODE=unix2003
SSH_AUTH_SOCK=/tmp/launch-******/Listeners
__CF_USER_TEXT_ENCODING=0x400:1:14
__CHECKFIX1436934=1
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/X11/bin:/opt/pdflabs/pdftk/bin:/usr/local/MacGPG2/bin:/usr/texbin
PWD=/
SHLVL=1
HOME=/Users/h12o
LOGNAME=h12o
DISPLAY=/tmp/launch-******/org.macosforge.xquartz:0
_=/usr/bin/printenv

やはりPWD=/となっていました。

比較のためにターミナルから./Printenv.app/Contents/MacOS/Printenv.shを実行すると、結果は以下のようになります。

LIBOVERLAY_SCROLLBAR=0
TERM_PROGRAM=Apple_Terminal
GPG_AGENT_INFO=/Users/h12o/.gnupg/S.gpg-agent:*****:1
TERM=xterm-256color
SHELL=/bin/bash
TMPDIR=/var/folders/**/******************************/*/
Apple_PubSub_Socket_Render=/tmp/launch-******/Render
TERM_PROGRAM_VERSION=326
ANDROID_SDK_ROOT=/opt/android-sdk
TERM_SESSION_ID=*******-****-****-****-************
USER=h12o
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:
SSH_AUTH_SOCK=/tmp/launch-******/Listeners
__CF_USER_TEXT_ENCODING=0x400:1:14
__CHECKFIX1436934=1
PATH=/Users/h12o/.cabal/bin:/Users/h12o/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Applications/Server.app/Contents/ServerRoot/usr/bin:/Applications/Server.app/Contents/ServerRoot/usr/sbin:/usr/local/MacGPG2/bin:/usr/texbin:/opt/android-sdk/tools:/opt/android-sdk/platform-tools:/usr/local/opt/coreutils/libexec/gnubin:/usr/local/opt/ruby/bin
_=/usr/bin/printenv
PWD=/Users/h12o
LANG=ja_JP.UTF-8
HOME=/Users/h12o
SHLVL=2
LOGNAME=h12o
DISPLAY=/tmp/launch-******/org.macosforge.xquartz:0
SECURITYSESSIONID=*****

PWD=/Users/h12oになっています。

なお、この時点でアプリケーションのアイコンはFinderの?デフォルトアイコンが表示されます。アイコンをどうするか、また/Applications/配下に置くかなど、さらに使い勝手を良くする方法に関しては各自の好みにお任せしたいと思います。また、テキストエディットのように読み書き可能なアプリケーションを使うのではなくX11のxmessageのようなダイアログ用アプリケーションを使う、といった工夫も考えられます。もしよりよい方法がありましたら教えてください。

45
49
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
45
49