Terminal.app からテキストエディターを開く方法を試してみました. ダブルクリックで開くアプリを環境設定用のアプリの中から起動したくて, アプリの起動法を調べ始めた中のことです. インターネットで調べていて open -a myapp.app
と open -a myapp
のどちらがよいのか混乱してきたということがきっかけで現状調査を思い立ちました.
調査結果の概要
- 標準ソフトは文献によくでてくる
open -a TextEdit
などで大丈夫です. - 正式っぽい使い方は
open -b com.apple.TextEdit
などのように-b
オプションを使う起動の仕方です. - アプリのデバッグなどで複数バージョンの動作を比較する状況では, フルパス名を指定して
open -a /Appliations/SageMath-9.0.app
などとします. - フルパス名に日本語が含まれている場合も, フルパス名でアプリ名を指定する方法は大丈夫です.
- 一部のアプリでは,
open -a SageMath-9.0
という起動の仕方ができません. -
open -a TextEdit
と/Applications/TextEdit.app/Contents/MacOS/TextEdit
でアプリの挙動に差異があります.
~/MyAppli.app
や ~/マイアプリ.app
をデバッグ中で複数バージョンの動作比較を行なっている状況で, デバッグ対象をダブルクリックと同等の動作で起動したい場合について表にまとめておきます.
コマンド | 可否 |
---|---|
open -a TextEdit |
可 |
open -b com.apple.TextEdit |
可 |
open -a ~/MyAppli.app |
可 |
open -a MyAppli.app |
可? |
open -a MyAppli |
不可 |
open -a ~/マイアプリ.app |
可 |
open -a マイアプリ.app |
可? |
/Applications/TextEdit.app/ Contents/MacOS/TextEdit
|
不可 |
~/MyAppli.app/Contents/MacOS/MyAppli |
不可 |
(長い絶対パス名を表に押し込むために途中にスペースを入れてありますがテストしたときの絶対パス名は途中にスペースも改行も入れていません.)
open
コマンドで自作アプリを起動する場合には, 同じベースネームのアプリが複数配置してある状況がありますので, アプリ開発の中の動作テストの場面で, 起動中のアプリからそのアプリの絶対パスの情報を調べるテクニックが欲しくなります. これは将来の調査課題として残りました. 想定する状況だけ記しておきます.
- 同じバージョンのコピーを複数のフォルダーに配置してしまった場合
- 異なるバージョンに同じベースネームを付けてしまった場合.
参考資料
2017年04月14日付の macOS Mojave 10.14.6 の man-page の open の記述と 寝坊した さんの「プログラミングと海外移動の情報マガジン」のページ 便利に使えるMacのopenコマンド を参考にしました.
実際に試した使用環境
バージョン情報は以下の通りです.
- macOS Mojave 10.14.6
- CotEditor 3.8.4
動作テストの仕方
ここでは , カレント・ディレクトリー内に MyTextFile.txt
というファイルを作成してある状況で MyTextFile.txt
を Terminal.app
内の bash
から開く例を調べます.
指定するアプリは macOS 標準の TextEdit.app
です.
Finder
やシステム環境設定
→言語と地域
の設定によっては TextEdit
, テキストエディット
, テキストエディット.app
などと表示されていると思います.
一時的に他のアプリを例として挙げる場合も出てきます.
アプリを絶対パスで指定してテキストファイルを開く
絶対パス名 (バックスラッシュで始まるフルパスネーム)による open
コマンドの起動の仕方が man-page に記載されていますので, なぞってみます.
コマンド:
myhome$ open -a /Applications/TextEdit.app MyTextFile.txt
動作: TextEdit.app
が MyTextFile.txt
を開いて前面に出てきます.
man-page にある例から少し起動の仕方を変更して試行錯誤した結果, 注意点がでてきました.
注意点 (できないこと):
- ファイル拡張子
.app
を取ると起動できません. -
open
は-a
の引数について相対パスとベースネームを区別しているようです. 例えば ,/Applications
にいるときにopen -a ./TextEdit.app
とopen -a TextEdit.app
で挙動が違います. - アプリのパスに相対パスは使えないようです.
- アプリの名前にシェルの alias は使えません.
- アプリの名前に Locale の表示名は使えません. (オプション
-a
の引数の中で/Applications
を/アプリケーション
に変えたりTextEdit
をテキストエディット
に変えたりすると, 起動できません.)
注意点 (できること):
- シェルの変数に絶対パス名を入れておいて展開させることは可能です. (
open
コマンドに引数を送る前にシェル側で処理する形で使う場合ですので,export
などで環境変数にしている変数以外の変数でも問題ありません.) - アプリの絶対パス名はアプリの絶対パス名へのシンボリック・リンクの絶対パス名でも構いません.
- アプリの絶対パス名はアプリの Mac エイリアス (別名 ) の絶対パス名でも構いません.
- 下記の 3通り全てについて, アプリの絶対パス名の後ろにスラッシュ
/
を追加して構いません.- アプリのパス名を直接使う場合, シェルの変数を展開して
open
コマンドに送る場合 - アプリへのシンボリック・リンクの絶対パス名を使う場合
- アプリへの Mac エイリアスの絶対パス名を使う場合
- アプリのパス名を直接使う場合, シェルの変数を展開して
注意点 (できること) の例1.
myhome$ te2day=/Applications/TextEdit.app/
myhome$ open -a $te2day MyTextFile.txt
注意点 (できること) の例2.
myhome$ open -a /Applications/TextEdit.app/ MyTextFile.txt
注意点 (工夫すればできること): アプリのファイル名に空白文字が含まれている場合は, 引用符かバックススラッシュによるエスケープを使って下さい. 下記の例はテキストファイルを開く例ではありませんがアプリの絶対パス名の扱いは同じです.
myhome$ open -a "/Applications/Font Book.app"
myhome$ open -a '/Applications/Font Book.app'
myhome$ open -a /Applications/Font\ Book.app
アプリをベースネームで指定してテキストファイルを開く
ベースネームはパス名からフォルダー名をはずしたものという雰囲気のものです. /Applications/Utilities/Terminal.app
のベースネームは Terminal.app
です. 技術的には, /Applications/Utilities/Terminal.app
自体がフォルダーだという事情で表現が難しいとろこですが
myhomt$ basename /Applications/Utilities/Terminal.app/
Terminal.app
myhome$ dirname /Applications/Utilities/Terminal.app/
/Applications/Utilities
とうコマンドの引数を変えて試すとわかるbasename
と dirname
の動作に準拠します.
/Applications/TextEdit.app
のベースネームは TextEdit.app
です.
myhome$ open -a TextEdit.app MyTextFile.txt
動作: TextEdit.app
が MyTextFile.txt
を開いて前面に出てきます.
注意点 (できないこと):
- アプリのベースネームの後ろにスラッシュ
/
を付けると起動できません. - アプリのシンボリック・リンクを
/Applications
やカレント・ディレクトリー に置いている場合でも , シンボリック・リンクのベースネームによってアプリを指定して起動することはできません. - アプリのMac エイリアスを
/Applications
やカレント・ディレクトリー に置いている場合でも , Mac エイリアスのベースネームによってアプリを指定して起動することはできません.
注意点(できてしまうこと):
- アプリのベースネームを小文字にしても起動できてしまいます. (もしかすると , case-insensitive file system の問題点かもしれません. case-sensitive file system では大文字と小文字が区別されて, 下記のおかしな例が不可になるかもしれません.)
悪い例 myhome$ open -a textedit.app MyTextFile.txt
疑問点:
- MacOS のアプリは
XXXX.app/Contents/Info.plist
の Bundle Name や Display Name というエントリーで名前を登録しています. この名前を使うのが MacOS Classic からの伝統につながるはずですが, 自作アプリのファイル名を変更して試してみると, アプリのファイル名のベースネームがopen
コマンドのアプリ名として通用しているようです. (CFBundleName
があって,CFBundleDisplayName
がない自作アプリを Automator で作成して調べました.) - インターネットで
open
コマンドの使い方を調べていると, 「アプリのフォルダーに移動してから ,open -a アプリのベースネーム
を実行する」という内容の記述や「アプリが/Applications
フォルダーにあるときは, アプリをベースネームで指定することができる」とう内容の記述があります. ところが, 自作アプリで調べてみると, カレント・フォルダーでもなく/Applications
フォルダーでもない場所に置いてあるアプリでもベースネームで指定することができるようです. MacOS X のバージョンが変わってきた中で動作が変化してしまったのかもしれません . セキュリティー対策からすると怖い方向の変化です.
アプリのベースネームから拡張子 .app
をはずした名前でアプリを指定テキストファイルを開く
/Applications/TextEdit.app
を例にするとベースネームは TextEdit.app
で拡張子 .app
をはずした名前は TextEdit
です.
myhome$ open -a TextEdit MyTextFile.txt
動作: TextEdit.app
が MyTextFile.txt
を開いて前面に出てきます.
注意点 (なぜかできること):
- アプリの名前を
TextEdit/
としても起動することができます. - インターネットで
open
コマンドの使い方を調べていると,.app
を省略して良いというページと省略してはいけないというページが両方出てくると思います.TextEdit
でも今回試した自作アプリでも.app
を省略した形でopen
コマンドが使えるのですが,SageMath-9.0.app
の場合はopen -a SageMath-9.0
もopen -a SageMath-9
も不可でした. ベースネームの中の.app
を省略できる条件は判然としないところがあります. もしかするとSageMath
を複数バージョン置いている状態がトラブルを起こしているのかもしれません. (ここの調査はTextEdit.app
以外はファイルを開く形ではないアプリの起動で行いました.)
注意点 (できないこと ):
- アプリの名前にシンボリック・リンクや Mac エイリアスのベースネームを使うことができない状況は拡張子
.app
をはずしても変わりません.
アプリを Bundle Identifier で指定して起動
アプリの Bundle Identifier はアプリの Info.plist で宣言してある名前で MacOS の中でのアプリの正式名称です. 調べ方は, 後で紹介します. ここでは, TextEdit.app
のBundle Identifier com.apple.TextEdit
を使います.
まず, man-page にある例をなぞります.
myhome$ open -b com.apple.TextEdit MyTextFile.txt
動作: TextEdit.app
が MyTextFile.txt
を開いて前面に出てきます.
MacOS はアプリのデータベースを作って, ファイルとアプリの関連付けやアプリの起動を行っています. そのデーターベースを調べると
com.apple.textedit
が canonical id:
として載っています. canonical
は「標準形に変換してから比較する」というときの「標準」に近い言葉ですので, Bundle Identifier として, com.apple.textedit
も試しました.
myhome$ open -b com.apple.textedit MyTextFile.txt
英字を小文字に変換する標準化が介在していると考えて
myhome$ open -b com.apple.Textedit MyTextFile.txt
も試しました.
どちらも, com.apple.TextEdit
の場合と同じ動作でした.
open
コマンドのオプションでテキストエディターを指定してテキストファイルを開く
open
コマンドに -e
オプションを指定すると TextEdit.app
でファイルを開きます. -e
オプションの代わりに -t
オプションを使うとデフォールト・テキストエディターでファイルを開きます. アプリを指定するオプションなしでファイルを開くと, そのファイルに関連付けられているアプリでファイルを開くことになります.
テキストファイルとテキストエディターの関連付けは, テキストエディター 2種 (TextEdit.app
, CotEditor.app
) を使って MyTextFile.txt
に対するファイル個別の関連付けとテキストファイル全般の関連付けの組み合わせ合計 4通りを考えることにしました.
この起動の仕方 3 通りと掛け合わせて 12通りの網羅テストを行いました.
コマンドごとに表にまとめます.
myhome$ open -e MyTextFile.txt
open -e MyTextFile.txt |
.txt --- TextEdit | .txt --- CotEditor |
---|---|---|
MyTextFile.txt --- TextEdit | TextEdit | TextEdit |
MyTextFile.txt --- CotEditor | TextEdit | TextEdit |
myhome$ open -t MyTextFile.txt
open -t MyTextFile.txt |
.txt --- TextEdit | .txt --- CotEditor |
---|---|---|
MyTextFile.txt --- TextEdit | TextEdit | CotEditor |
MyTextFile.txt --- CotEditor | TextEdit | CotEditor |
myhome$ open MyTextFile.txt
open MyTextFile.txt |
.txt --- TextEdit | .txt --- CotEditor |
---|---|---|
MyTextFile.txt --- TextEdit | TextEdit | TextEdit |
MyTextFile.txt --- CotEditor | CotEditor | CotEditor |
動作: 以上の 12通のどの場合でも, 表に記載のテキストエディターが MyTextFile.txt
を開いて前面に出てきました.
MacOS はインストール直後の状態では デフォールト・テキストエディターが TextEdit.app
になっています.
注意点:
-
open
コマンドは-a TextEdit
とテキストファイルのファイル名の片方なら省略することができますが, 両方省略するとヘルプを表示して終了してしまいます. -
open -e
とopen -t
はテキストエディターを起動します. このときテキストエディターは新規ファイルの編集ウィンドウで前面に出てきます.
アプリの MacOS 実行形式を直接指定してテキストファイルを開く
アプリの MacOS 実行形式はアプリから相対パス Contents/MacOS/
の位置のフォルダーに入れるのが慣例です. 実行形式のファイル名のベースネームは Info.plist
に入っている推測していますが, 調査はまだです.
$ plutil -p /Applications/TextEdit.app/Contents/Info.plist | egrep -e Executable
"CFBundleExecutable" => "TextEdit"
TextEdit.app
の場合は, 下記のコマンドで開始することができます.
myhome$ /Applications/TextEdit.app/Contents/MacOS/TextEdit
動作: TextEdit.app
は起動しますが, ウィンドウは前面に出てきません.
注意点:
- この起動の仕方の
TextEdit
は挙動不審です. ファイル名を指定した場合, 起動した側のカレント・ディレクトリからではなくホーム・フォルダーから相対的にファイルを探すようです.
MacOS のアプリのデータベース の調べ方と Mac アプリの情報の調べ方
寝坊した さんの 便利に使えるMacのopenコマンド で教わったコマンドの出力から id
と com.apple.TextEdit
の行を egrep
で抜き出してみました.
myhome$ cd /
myhome$ cd System/Library/Frameworks/CoreServices.framework
myhome$ cd Frameworks/LaunchServices.framework/Support/
myhome$ ./lsregister -dump | egrep -i -e 'id.*com.apple.TextEdit'
identifier: com.apple.TextEdit (0x80003de5)
canonical id: com.apple.textedit (0x80003de4)
CFBundleIdentifier = "com.apple.TextEdit";
"com.apple.application-identifier" = "com.apple.TextEdit";
最初にルートへ cd
しているのは, 次の 2行の cd 先を両方とも相対パスにして書式を揃えるためです. egrep
のオプション -i
は大文字と小文字を同一視する指示です. -e
オプションのパラメーターは, egrep
にワイルドカードの正則表現 .*
を渡すために引用符で囲ってあります. よく考えると, id: com-apple-TextEdit
も引っかかる検索になっていますが, 出力に混乱が起きていないので問題ないと思います.
アプリの情報を直接見るには, plutil -p
を使います.
myhome$ cd /Applications/TextEdit.app/Contents
myhome$ plutil -p Info.plist | egrep -e CFBundleIdentifier
"CFBundleIdentifier" => "com.apple.TextEdit"
調査結果
- 大勢が使っている標準アプリの起動は大勢に合わせておくのが無難で,
open -a TextEdit
,open -a Terminal
などという形で-a
オプションが使えます. - 正式っぽい使い方は, アプリの名前を書く代わりに
-b
オプションに続けて Bundle Identifier を書いてアプリを指定する仕方のようです.TextEdit.app
を起動するときはopen -b com.apple.TextEdit
,Terminal.app
を起動するときはopen -b com.apple.Terminal
となるようです. - 一方, 自作ソフトや発展段階のアプリで複数バージョンの動作を比較する状況のときはアプリを絶対パス名で指定して
open -a /Applications/SageMath-9.0.app
とした方がよいようです. この場合は,open -a SageMath-9.0
では起動でこきないことがあるようです.open -b org.sagemath.Sage
ではアプリのバージョンが指定できません. 試してみると, LaunchPad に挙がっているバージョンが起動するようですが, SageMath-X.X.app で調べただけの状況です. - 複数バージョンでファイル名の中のバージョンナンバーを変えてある場合は,
open -a SageMath-9.0.app
という起動の仕方でも大丈夫なようです. 他のバージョンがSageMath-8.6.app
とSageMath-8.9.app
というファイル名になっているような場合で調べた結果です. -
Finder
の日本語の表示ではTextEdit.app
はテキストエディット
になっていて,/Applications
フォルダーは/アプリケーション
になっていますが,open
コマンドではこの表示名は使えないようです. 文字コードを変えるなどのトリックで表示名による指定ができる可能性については調査していません. - アプリのファイル名に日本語を使っている場合も,
open -a マイアプリ.app
やopen -a ~/マイアプリ.app
などは使えるようです. -
open -a TextEdit
と/Applications/TextEdit.app/Contents/MacOS/TextEdit
でアプリの挙動に差異があります.