AppleScript でファイルの参照

2016/02/25

さて。AppleScript でファイルを開くいろいろな方法をみてきました。

Finder や System Events などのアプリケーションや StandardAdditions.osax のファイル選択ダイアログを使えば、処理したいファイルの指定はそれほど難しいものではありません。

しかし、スクリプトの中ではもっと直接的にファイルの指定を行いたいときが多々あります。

ということで、今回は AppleScript で利用するファイルの参照、パスの話です。


HFS パス

OS X 以前の話です。その頃 AppleScript はコロン(:)区切りのパスを使っていました。

ユーザー cherry の書類フォルダの中にある style.css というファイルを表すと、次のようになります。

-- Macintosh HD は起動ディスク
"Macintosh HD:Users:cherry:Documents:style.css"

このコロン区切りのパスを「HFS パス」と呼びます。HFS は OS X のファイルシステムですね。このパスはルート(この例だと起動ディスク)から書き始めます。だから、他の人の環境だと異なっているかもしれませんし、外部ディスクになるとルートも変わります。

現在の AppleScript だとルートの省略ができるようで、以下のような書き方でもありです

-- 起動ディスク以下の Applications フォルダ
"Applications:"

HFS パスではコロンまでが一つのディレクトリです。

"Macintosh HD:" -- ルートディレクトリ
"Macintosh HD:Users:cherry:Documents:" -- 書類フォルダ
"Macintosh HD:Users:cherry:Documents:style.css" -- style.css ファイル

最初のコロンまでが起動ディスク(もしくはルートディレクトリ)を表しています。最後にコロンがつくとディレクトリ(フォルダ)、そうでないならファイルとみなされます。

OS X 以前から利用されていたということもあり、AppleScript ではこの HFS パスを多用します。これは現在(OS X 10.11)でも変わっていません。

POSIX パス

POSIX パスは UNIX ベースの OS X ではなじみが深いものです。スラッシュ区切りのこのパスは、さまざまな場面で目にするものです。

先ほどのユーザー cherry の書類フォルダの中にある style.css を POSIX パスで表すと次のようになります。

"/Users/cherry/Documents/style.css"

簡潔ですね。この POSIX パスは特別なことをしなくても AppleScript では(文字列として)利用できます。

AppleScript というのはグルー言語です。いろんな機能を組み合わせて複雑なバッチ処理を行うことを目的としています。シェルスクリプトなんかと同じですね。

UNIX ベースの OS X なんだからバッチ処理はシェルスクリプトでいいじゃないか、と言えばその通りなのですが、AppleScript の優位性というのは各種アプリケーションを操作することができることです。

もともとはアプリケーションの自動化が主な目的だったのですが、現在では AppleScript を中心にシェル(を通しての外部プログラミング言語)、Objective-C、JavaScript...と、いろいろなプログラミング言語を結びつける役割も果たしています。

こういう特性のため AppleScript でも POSIX パスを利用することが多々あります。ファイルの選択は AppleScript で行って処理はシェルで行う...といった感じですね。

ファイル参照のためのクラス

POSIX パスも HFS パスもファイルやフォルダの場所を示すための記述方式にすぎません。ぶっちゃけただの文字列です。このままでは AppleScript ではファイルの参照として認識しません。

では AppleScript でファイルを参照するにはどうするのかというと、alias、もしくは file クラスを利用します。

ごくおおざっぱにいってしまえば、alias クラスは『既にあるファイルを指定するためのクラス』で file クラスは『存在していないファイルを指定するためのクラス』です。

既にファイルがある場合に使うのが alias クラスです。

alias "Macintosh HD:Users:cherry:Desktop:Work:main.html"

デスクトップの Work フォルダにある main.html というファイルを指定しています。このとき、この場所にファイルがないと実行時にエラーになります(古いバージョンの AppleScript ではコンパイル時にエラーになる)。

AppleScript は実行時に alias で指定されたファイルやフォルダを記憶します。記憶しておくことで、次回からはファイルやフォルダを追跡します。つまり、ファイルやフォルダを移動させたり、名前を変更しても大丈夫なんです。

次のスクリプトを試してみましょう。

try
-- 初回実行時はエラーになる
theFile
on error
-- エラーが起きるとここでファイルを選択する
set theFile to choose file
end try
-- 適当な場所に移動させる
set folderList to {path to desktop folder, path to music folder, path to documents folder, path to movies folder}
set thisFolder to some item of folderList
repeat until (theFile as text) does not start with thisFolder
set thisFolder to some item of folderList
end repeat
tell application id "com.apple.finder"
activate
-- 選択されたファイルの場所を確認
set msg to "現在の場所から移動します" & return & return & "現在: " & (theFile as text) & return
set msg to msg & "移動先: " & (thisFolder as text)
display dialog msg
move theFile to thisFolder
end tell

初回実行時は変数 theFile が未定義なので必ずエラーになります。エラーが起きるとファイル選択を求められます。その後、現在の場所を表示し、適当な場所に移動させます。

もう一度、実行してみましょう。ファイルは元の場所にないにも関わらず、ファイル選択を求められませんし、ファイルは再度異なった場所に移動されます。

alias は指定されたファイルやフォルダの情報を記憶します。このため、ファイルの位置や名前が変更されても追跡することができます。そういう特殊なもののため、実行時に指定するファイルやフォルダが存在しないとエラーになります。

いまいちピンとこない...という方もいると思われます。もうちょっと直感的に理解できる仕組みが Finder にあります。それは、Finder で作るエイリアス(「ファイル」メニューの「エイリアスを作成」)です。

この Finder で作るエイリアスと AppleScript の alias クラスは同じ仕組みです。

では、file クラスをみてみましょう。

file クラスは alias とは異なり、常に一つの場所を参照します。指定された場所にファイルがなければファイルを作成し、あれば、そのファイルを使用します。alias のようにオリジナルのファイルを追跡しません。

例えば、以下のようにすればデスクトップに「new file.md」というファイルを作成します。

-- ファイルのパスを文字列から作る
set theFile to (path to desktop as text) & "new file.md"
-- パスを file クラスとして扱い新規ファイルを作成
set fh to open for access file theFile with write permission
close access fh

再度このスクリプトを実行すると、すでにある「new file.md」に上書きします(なにもデータを追加していませんが)。「new file.md」を他の場所に移動させ、再度実行すると同じ場所に同じ名前でファイルを作成します。

このように file クラスは常に指定された場所だけを参照します。

aliasfile は、それぞれ同じようにファイルを参照しますが、その意味するところは異なっています。目的に合わせて利用することが大事です。

パスの相互変換

現在では、POSIX パスでファイルを指定するのが、記述のしやすさや汎用性の点からいっても楽です。指定したいファイルやフォルダをそのまま Script Editor.app のドキュメントにドラッグ & ドロップして挿入もできますし。

しかし、AppleScript では POSIX パスをそのまま利用するということは稀です。もう少し厳密に書くと、AppleScript やアプリケーションで定義されている命令やクラスが POSIX パスを受け取るようになっていません。

パスの指定は POSIX パスが楽だけど、AppleScript の命令などで利用するにはどうすればいいのか?

そのためにパスの変換を行います。パスの変換方法を覚えれば、HFS パスと POSIX パスを相互に変換できます。

変換には as 演算子を使います。as 演算子は型の変換を行う演算子です。

set num to 29.87
class of num
--> real
-- 整数値に変換
set num to num as integer
class of num
--> integer
-- 文字列に変換
set num to num as text
class of num
--> text

変換できない値を変換しようとするとエラーになりますが、as による型変換は頻繁に利用するので覚えておきましょう。

AppleScript ではファイル参照に利用するためのクラスが 3 つあります。aliasfilePOSIX file です。aliasfile クラスは後で説明します。POSIX パスを変換するために利用するのが POSIX file です。

POSIX file というのはちょっと特殊なクラスで POSIX パスを HFS パスに変換するためだけに利用します。基本的には後で説明する file クラスと同等のものです。

-- Applications フォルダ内の Mail.app
"/Applications/Mail.app" as POSIX file
--> file "Macintosh HD:Applications:Mail.app"

変換すると file クラスのパスが返ってきます。この変換は頻繁に利用するので、わざわざ as で変換しなくてもいいようになっています。

-- 次の書き方でも可
POSIX file "/Applications/Mail.app"
--> file "Macintosh HD:Applications:Mail.app"

ちなみに POSIX パスでは ~ が現在ログインしているユーザーのホームを表していますが、AppleScript では正しく解釈されません。POSIX パスを利用するときは相対パスではなく、絶対パスを使ってください。

fileas 演算子で alias に変換することもできます。

set theFolder to POSIX file "/usr/local/bin/"
tell application id "com.apple.finder" to open (theFolder as alias)

file クラスも alias クラスも as 演算子で HFS パス文字列に変換できます。

set theFolder to POSIX file "/usr/local/bin/"
theFolder as text
--> "Macintosh HD:usr:local:bin:"

次に HFS パスを POSIX パスに変換するにはどうするのか?

alias クラスと file クラスはそれぞれ、POSIX path という属性を持っているので、これを利用します。

-- POSIX パスを file に変換
set theFile to POSIX file "/Applications/Utilities/X11.app"
--> file "Macintosh HD:Applications:Utilities:X11.app"
-- file を POSIX パスに変換
POSIX path of theFile
--> "/Applications/Utilities/X11.app"

POSIX file はクラスだけど、POSIX path は属性です。このへんを勘違いしないようにしましょう。

いろいろなパスを取得する

スクリプトからファイルを参照するための記述方法をみてきました。今度はスクリプトの中からいろいろなパスを取得してみましょう。

StandardAddtions.osax に path to という命令があります。この命令は特定の場所を返してくれる便利な命令です。

例えば、実行しているスクリプトの場所を得るには次のようにします。

path to me

スクリプトが保存されているならファイルの場所が返ってきます。では、ログインしているユーザーのホームを取得してみます。

path to home folder

どんどんいきましょう。

-- 現在のユーザーの書類フォルダ
path to documents folder
-- 現在のユーザーのピクチャーフォルダ
path to pictures folder
-- 現在のユーザーのムービーフォルダ
path to movies folder
-- 現在のユーザーのデスクトップ
path to desktop
-- 現在のユーザーのダウンロードフォルダ
path to downloads folder

これらのパスを path to で取得するのはユーザーによってユーザー名や起動ディスク名などが異なるからですね。異なっていても同じようにスクリプトを動かすために path to を使います。

では、次のスクリプトを実行してみましょう。

path to library folder

今度はユーザーのライブラリフォルダの場所が返ってくるかと思いきや、違う場所が返ってきました。

OS X にはライブラリフォルダが複数箇所にあります。システムが利用するもの、ログインしている全ユーザーが利用するもの、そして、現在ログインしているユーザーが使用するもの。これらのうちどのライブラリフォルダかを指定していないため、予想と異なった場所が返ってきたのです。

path to 命令には from というオプションがあり、このオプションでどの場所かを指定します。

-- 現在のユーザーのライブラリフォルダ
path to library folder from user domain
-- 全ユーザーが利用するライブラリフォルダ
path to library folder from local domain
-- システムが利用するライブラリフォルダ
path to library folder from system domain

このように複数箇所にあるフォルダのパスを得るときは from による場所の指定を忘れないようにしましょう。

また、path to 命令には as オプションがあり、パスを alias で取得するか、文字列で取得するかを指定することができます。デフォルトでは alias でパスが返ってきます。

文字列で取得するのは、起点となるパスから特定のファイルを指定するためです。ユーザーの書類フォルダの中にある style.css ファイルを取得するなら次のようにします。

set documentsFolder to path to documents folder as text
set theFile to documentsFolder & "style.css"

これで各環境におけるユーザー名の違いや起動ディスク名の違いを考慮する必要がなくなります。

特定のフォルダのパスを文字列で取得し、目的のファイル名と文字列の結合を行い、filealias、もしくは POSIX パスに変換...と、これがファイル参照の一連の手続きですが、この操作は頻繁に行うのでいろいろと試して慣れておくといいでしょう。

ときどき目にする勘違いなのですが、これが AppleScript におけるファイル参照であって、Finder や System Events 等のファイルを扱うアプリケーションによるファイルの参照とは別のものです。これらのアプリケーションにおけるファイルの参照はファイルの参照ではなく、オブジェクトの参照だということを間違えないようにしましょう。

0 件のコメント :

コメントを投稿