AppleScript でファイルを開いてみましょ

Finder でファイルをダブルクリックし、ファイルを開き、アプリケーションで処理をする。もしくは、Finder でファイルを選択し、それをアプリケーションアイコンにドラッグ & ドロップしてファイルを開く...。

たかだかファイルやフォルダを開くだけなのですが、日常的にやっている作業でもあります。それゆえに自動化の恩恵はそれなりにあるのではないでしょうか。

この作業を Applecrip で代替してみましょう。


例えば未対応なアプリケーションで

アプリケーションの起動と終了」でも書いたようにアプリケーションは AppleScript に対応しているものとそうでないものがあります。アプリケーションが AppleScript に対応していてもどのていど対応しているかが異なります。

しかし、ファイルを開くということだけならほとんどのアプリケーションで利用することができます。アーカイブユーティリティ.app は OS X に標準でついてくる圧縮されたファイルを解凍するアプリケーションですが、これは AppleScript に対応していません。しかし、基本的な命令をうけつけるアプリケーションでもあります。

では、AppleScript からファイルを開くとどうなるか?

-- デスクトップにある Archive.zip を指定
set theFile to (path to desktop folder as text) & "Archive.zip"
tell application "Archive Utility"
    -- アーカイブユーティリティで開く
    open file theFile
end tell

予想通り、圧縮されたファイルが解凍されます。このようなアプリケーションは(AppleScript で操作できているように見えますが)「AppleScript 未対応」です。本来の AppleScript に対応しているアプリケーションは「用語説明を持っている」アプリケーションです。分かりにくいのですがここでは未対応に分類します。

と、こういうことを踏まえて、AppleScript でどこまでできるのか?

ファイルを開く基本は Finder です

AppleScript に対応していなくてもファイルを開くだけであれば、Finder を通せばどんなファイルでも開けます(そのファイルを開けるアプリケーションがあれば)。

tell application id "com.apple.finder"
    -- ウィンドウがなければ終了
    if not (front Finder window exists) then return
    tell front Finder window
        -- 前面のウィンドウにある拡張子が mp4 のファイルを取得
        set fileList to document files whose name extension is "mp4"
    end tell
    -- ファイルを開く
    open fileList
end tell

これは、Finder でファイルをダブルクッリクする動作と同じで、デフォルトのアプリケーションでファイルを開きます。なにも変更していないなら、QuickTime Player が起動してファイルが表示されます。

また、Finder は開くアプリケーションを指定してファイルを開くことができます。これも AppleScript で制御できます。openusing オプションを利用します。

tell application id "com.apple.finder"
    -- ウィンドウがなければ終了
    if not (front Finder window exists) then return
    tell front Finder window
        -- 前面のウィンドウにある拡張子が mp4 のファイルを取得
        set fileList to document files whose name extension is "mp4"
    end tell
    -- ファイルを VLC.app を使って開く
    open fileList using (path to application "VLC")
end tell

この方法を使えば、テキストファイルなら CotEditor で、画像ファイルなら Photoshop でといったこともできますね。

open と Finder の open の違い

AppleScript を書き始めたころ理解しにくかったのが、同じ命令がいくつもあることでした。

Finder の open は Finder で定義されているもので using なんていう便利なオプションが追加されています。

もう一方の open は AppleScript で定義されているもので using なんてオプションはありません。でもね、見た目は一緒なんです。では、それらをどうやって見分けるのか?

これらの見分け方は命令を送っている対象が誰か?で分かります。

QuickTime Player は AppleScript に対応しており、open 命令を持っています。

tell application "QuickTime Player"
    open fileList
end tell

だけど、using というオプションはないのでただ、ファイルを開くだけです。

命令を送っている対象というのは tell 構文で指定されています。tell で指定されていないなら、それは AppleScript に最終的に送られます。

tell 構文というのは命令を送る対象を指定する構文なので、対象はアプリケーションでなくてもかまいません。

set theList to {1, 2, 4, 10.1, "文字", 0.1, "abc"}
tell theList
    length
    --> 7
    strings
    --> {"文字", "abc"}
    numbers
    --> {1, 2, 4, 10.1, 0.1}
    reverse
    --> {"abc", 0.1, "文字", 10.1, 4, 2, 1}
end tell

どのアプリケーションが持っている命令か?どこに命令を送っているか?というのは結構重要なことでこれを見極めていないとスクリプトがエラーになる、動かないといった原因になります。

再びの URL Scheme

以前にも URL Scheme のことを書いたことがありますが、あれは iPhone アプリのことでした。現在では OS X のアプリケーションでも AppleScript には対応していないけど、URL Scheme は設定されているというアプリケーションが増えてきました。それらを使ってファイルを開いてみましょう。

Apple 純正のものだと辞書.app や FaceTime.app、App Store.app、連絡先.app などがわりと有名ですね。

URL を AppleScript で開くには open location 命令を使います。この命令は URL をデフォルトのアプリケーションで開く命令です。http で始まる URL なら Safari が起動しますし、itms で始まるなら iTunes が起動します。

ちょっと余談なんですが、open location は StandardAdditions.osax という AppleScript 独自の機能拡張で定義されています。特別に変な使い方をしていない限り、StandardAdditions.osax は必ずインストールされています。

普段は意識せずに使っているので気がつきませんが、StandardAdditions.osax は AppleScript に足りない機能を追加するかなり重要なものです。AppleScript 自体に定義されている命令なんて activatecopycountgetlaunchrunset ぐらいです(いま delay の説明を見ていたら delay はビルトインコマンドだと書かれていた。なら、StandardAdditions.osax の用語説明にのせるなよ。っていうかいつのまに変わった?)。

たかだかこれだけの命令しかないので StandardAdditions.osax がないとなにもできなかったりします。なんでこのことを長々と書いているかというと、どこで定義されている命令かということが重要なのと、OS X 10.8 以降では use を使って StandardAddition.osax の命令を使うよって宣言が必要になるからです(まぁ、面倒)。

閑話休題。

URL Scheme は基本的にはそのまま開いてしまえば、アプリケーションが起動します。

-- 連絡先.app を起動
open location "addressbook://"
-- カレンダー.app を起動
open location "ical://"
-- 辞書.app を起動
open location "dict://"
-- FaceTime.app を起動
open location "facetime://"
-- App Store.app をセキュアに起動
open location "macappstores://"

しかし、URL Scheme には便利なオプションがあります。例えば、連絡先.app なら登録している人の ID を指定して編集を行う事ができます。

tell application id "com.apple.AddressBook"
    set theList to selection
    if theList is {} then return
    set personID to id of item 1 of theList
end tell
open location "addressbook://" & personID & "?edit"

ほとんど意味のないサンプルですが、URL Scheme を使うとこういうことが出来ます。が、問題なのは URL Scheme に渡すことができるオプションや値の説明がほとんどない、ということです。

マップ.app の URL Scheme は Map Links で説明がありますが、こういう説明はほとんどの場合ありません。なので自分で検索して使い方を見つけるしかないのが現状です。これが、URL Scheme の問題点。

Apple のアプリケーションでさえまともな説明がないのですから、その他のアプリケーションなんかほとんど使い方が分かりません。使えると便利そうなのだけど、使い勝手があまり考慮されていないという...。

自分の環境で使える URL Scheme を調べるには「自分のMacで使えるURLスキームをリスト表示するコマンド - Macの手書き説明書」を参考にしてみてください。

OS X 上での URL Scheme はアプリケーションで設定されているものを使うより、自分で好きな URL Scheme を作ってそれを使うというのが便利な気がします。

この方法を使えば、AppleScript でなんでもかんでも処理できてしまいますね。

open ハンドラを使ってみる

最後に話を戻して...open についてもう一度。

これまで書いてきたように open をそのまま使ってファイルをアプリケーションに渡す...というのは AppleScript ではどちらかというとあまり利用されていない使い方だと思います。

では、どういう使い方をするのかというと open ハンドラを使ってドロップレットを作る...というのがよく見かけるものです。

on open theseItems
    -- ドラッグ & ドロップされた項目を処理します
    repeat with thisItem in theseItems
        -- ここのファイル処理を記述します
    end repeat
end open

これを Script Editor.app でアプリケーションとして保存すると、ドラッグ & ドロップを受け入れるアプリケーション(ドロップレットと呼ばれたりします)になります。

そうなんです。スクリプトはアプリケーションとして保存することができるのです。

on run
    -- ここに起動したときの処理
    display dialog "run イベントが呼び出されました"
end run
on open theseItems
    -- ドラッグ & ドロップされた項目を処理します
    display dialog "open イベントが呼び出されました"
    repeat with thisItem in theseItems
        -- ここのファイル処理を記述します
    end repeat
end open
on reopen
    -- ここに reopen イベントを受け取ったときの処理
    display dialog "reopen イベントが呼び出されました"
end reopen
on quit
    -- ここに終了時の処理
    display dialog "quit イベントが呼び出されました"
    continue quit
end quit
on idle
    -- ここに一定時間ごとに行う処理
    display dialog "idle イベントの定期処理です"
    return 60
end idle

このスクリプトを「実行後、自動的に終了しない」アプリケーションとして保存します。起動させると最初に runidle が呼び出されます。idle はこの後、60 秒後に再度呼び出されます。

Dock にあるアイコンをクリックすると reopen が呼び出されます。Finder からなんらかの項目をドラッグ & ドロップすると open が呼び出されます。終了させると quit が呼び出されます。

完全にアプリケーションですね。で、このスクリプトをみてなにか思いつかないでしょうか?

そうです。先に書いた「基本的な命令を受けつけるアプリケーション」そのものです。実のところ、このサンプルを通しての方が「基本的な命令を受け付けるアプリケーション」っていうものが理解しやすいと思います。それらのアプリケーションはこういう中身をしているんだ、と(ごくごく乱暴にまとめてしまっていますが、動作原理を知る分にはいいでしょう...?)。

起動中のアプリケーションに run を送ったとき、なにをするかはアプリケーション次第、と書きました。run は基本的には起動時に一回処理されるだけなのですが、このサンプルをみるともう一回ダイアログが表示されますね。

open ハンドラがあれば外部からの AppleScript でファイルを開くことができます。reopen ハンドラがあれば、Dock のアプリケーションアイコンのクリックで動作します。で、どんな処理をするかはアプリケーション次第です。

こういう AppleScript アプリケーションを作って外部から操作したりするとより AppleScript の理解ははやまると思います。

では、実際に open ハンドラを使ったサンプルを作ってみます。

Finder でファイルをダブルクリックすると通常ならそのまま設定されているアプリケーションでファイルが開かれます。例えば、拡張子 md の Markdown 書類だと Xcode で開かれたりします(Xcode がインストールされていなるなら)。しかし、Atom で開きたい、もしくは CotEditor で開きたいなんて場合もあります。

Finder の「情報をみる」でファイルを開くアプリケーションを変更することはできますが、それも面倒だったりします。

特定のファイルだったら、全部 CotEditor で開いてしまえ、というものを作りましょう。が、なるべく手間をかけずにやってしまいたい。


これをアプリケーションとして保存します。拡張子 md、html、json、py のファイルをドラッグ & ドロップすることで CotEditor でファイルを開くことができます。これら以外のファイルだった場合は Finder に処理を任せてしまいます。拡張子を追加すれば、他のファイルにも対応できます。

これでいちいちデフォルトのアプリケーションを変更する必要もないですし、Finder のウィンドウのツールバーにでも置いておけば、どこからでも利用できます。また、デフォルトのアプリケーションで開きたいのなら Finder でダブルクリックすれば事足ります。

ファイルを開くってことだけで結構いろいろできるでしょう?

...と、これで話が終わればいいんですが、初心者向きのスクリプトばかりで面白みがないなぁという人(誰だ、それは)向けに。

以下は完全に蛇足です。


本当は最初に書いたスクリプトはこれなんですけどね。分かりにくいだろうし、説明も面倒なことになりそうだし...ということで採用を見送りました。

こっちの方がカスタマイズしやすいし、シンプルなんだけどね(自画自賛)。

あと、通常なら Finder でファイルをダブルクリックして開くとデフォルトのアプリケーションが起動します。

が、これを Finder のダブルクリックで AppleScript で作ったアプリケーションを起動させてしまえば、いいんじゃねと思ったのでそんなこともやってみました。例えば、JPEG ファイルをダブルクリック、AppleScript でリサイズ、Mail.app で開くみたいな感じです。

まぁ、作ってからドロップレットでいいじゃんと反省したのですが、単純に Finder のダブルクリックに反応させるにはどうしたらいいのだろう、と思ったのです。

作り方は Info.plist を編集するだけでできます。

まぁ、本当の蛇足ですね。これは。

1 件のコメント :

  1. 通りがかりの者です。
    AppleScriptの書き方を調べたくて、参考にさせていただきました。
    1箇所、「クッリク」というtypoがあります。

    返信削除