ファイル指定を覚えよう

ファイルパスと区切り文字

 Finderでファイルを扱う時には、file "名前" of folder "名前" of disk "名前"というようなオブジェクトをつなげた参照を使っていましたが、このような参照はアプリケーションのtellブロックの中でしか使えません。
 そこで、今回はもっと汎用的に使えるファイル指定形式を紹介します。

 ボリューム内にあるファイルを指定するには、ディスクの階層を次々とたどっていく必要があります。
 この道筋を「パス(path)」と呼び、区切り文字でフォルダをつないで表現します。

 ファイルの区切り文字はOSやプログラミング言語によって異なります(注1)。

 UNIX系のOSで使われる「 / 」区切りのパスの事を特に「POSIXパス」と言います(注2)。
 JavaScriptやPerl、Ruby、Pythonなどの他の言語との連携、特にUNIXシェル(ターミナル)との連携で、POSIXパスを使うことが多いでしょう。
 Finderのフォルダウインドウのタイトルバー表示もPOSIXパスですし、OS Xの基本的パス形式と言えます。

 Macは、HFS(Hierarchical File System)またはHFS+というファイル管理形式を使ってファイルを扱っています(注3)。
 Hierarchicalは、「階層制の」「階層的な」という意味の形容詞で、HFSは「階層型のファイル管理システム」という意味になります。
 この言葉のとおり、HFS/HFS+では階層構造(注4)でファイルを管理しています。Finderの[表示]-[リスト]を選択すると、階層構造がよく分かるでしょう。
 HFSではファイル名を「 : 」(コロン)で区切って使います。
 以前はこのHFSパスがMacの主流だったのですが、現在はこの形式を使わなくても、AppleScriptが書けます。
 ただし、公開されているスクリプトでもよく使われていますし、読める程度にはなっておいたほうがいいでしょう。

POSIXパス

 例えば、起動ボリューム(注1)の"テキスト"フォルダにある"日記"フォルダ内の"2000年の日記.txt"ファイルをPOSIXパスで指定するには、次のように書きます(注2)。

"/テキスト/日記/2000年の日記.txt"

 フォルダを指定する場合は、最後にスラッシュを付けます。

"/テキスト/日記/"

 エディタのウインドウにファイルをドロップすると、簡単にPOSIXパスを取得できるので、非常に便利です。
 ちなみに、ファイル名だけ貼り付けたい場合、Finderでファイルを選択してコピーを行った後、エディタでペーストします。

 AppleScriptでは文字列としてパスをそのまま使うほか、ファイル参照としても扱います。
 ファイル参照を使ったファイルの指定方法は、Finderのtellブロックにある必要がないので、OSAXでよく使われます。
 POSIXパスによるファイル参照(注3)は、次のように書きます。

POSIX file "/何か架空の/パスの/ファイル" -- (注4)
	--> file "HD:何か架空の:パスの:ファイル"

 AppleScriptはMac OS X以前のOSから存在する言語なので、結果に現れるファイル参照の表示形式は「 : 」区切りになっています。
 とはいえ使用上は、あまり気にする必要はありません。
 最初の「HD」の部分は、各環境によって異なる名前(起動ボリュームの名前)が入ります。

 POSIXパスの部分の文字列は、変数に入っていても構いません。
 次のスクリプトは、ファイル情報を持った「レコード」を結果ウィンドウに表示します。

set thePath to "/何か架空の/パスの/ファイル"
info for POSIX file thePath

 ファイル参照そのものを変数に入れておくこともできます。

set theFile to POSIX file "/何か架空の/パスの/ファイル"
info for theFile

 もちろん、Finderや一般のソフトで使用できる「アプリケーション命令」でも、このファイル参照を使えます。
 ofでオブジェクトをつなぐよりも短く書けるので便利です。

 このファイル参照は、ファイルの場所をしめす住所のようなものですから、その場所にファイルが存在していなくても指定できます。
 それから、最初はファイルが存在して後で、ファイルが移動されたとしても、同じ場所をさしています。
 ですから、ファイルがある前提で処理をするだけでなく、ファイルが存在していない場合も考えて、スクリプトを書く必要があります。

HFSパス

 今度は「 : 」区切りのHFSパスを使ってみましょう。

"HD:テキスト:日記:2000年の日記.txt"

 フォルダを指定する場合は、最後にコロンを付けます。

"HD:テキスト:日記:"

 頭に「 : 」をつけると、POSIXパスと同様に、起動ボリュームを省略できます(注1)。

":テキスト:日記:2000年の日記.txt"

 ファイル参照は、fileに続けてパス文字列を書くだけです。
 POSIX fileと同様に、パスの文字列を変数に入れて指定することもできます)。

set thePath to "HD:テキスト:日記:2000年の日記.txt"
info for file thePath

 ファイル参照形式を直接変数に代入する事はできません(注2)。
 つまりset a to file "test"はエラーとなります。  変数に代入する際は、a reference to演算子(注3)を使い、次のように書きます。

set theFile to a reference to file "HD:テキスト:日記:2000年の日記.txt"

 もちろん、この形式のファイル参照も「アプリケーション命令」で使えます。
 ただし、Finderの持っているfileオブジェクトと混乱してしまうため、Finderのtellブロックで使う時は気をつけましょう。

エイリアス値

 今度は、より柔軟性の高いファイルの指定方法であるエイリアス値を紹介します。
 書式は、aliasに続けて文字列、あるいはファイル参照を書くというものです。

 したがって、POSIXパスを使ってエイリアス値を表現する場合は次のようになります。

alias POSIX file "POSIXパス"

 この方法でファイルを指定しておけば、スクリプトの実行中にファイルを移動させたり名前を変更した場合でも、最初に指定したファイルを追跡します。

 エイリアスは、まずパスをたどってファイルに携帯電話を渡しておき、あとは携帯電話を使って指定したファイルを呼び出すような仕組みです。
 つまり、場所や名前が変わっても固有の電話番号を使ってファイルを指定できるわけです。
 そして、この電話番号こそが「エイリアス値」です。

 ただし、構文確認を行う際にパスで指定したファイル(携帯電話を渡す相手)がないとエラーが発生してしまいます。
 つまり、スクリプト中で新規にファイルを作る場合など、実際には(まだ)存在しないファイルの指定には使えません。

 エイリアス値は、値であるので変数に代入して使えます。
 次のスクリプトは "/"、つまり起動ボリュームのパスを元にしたエイリアス値を、変数に代入しています。

set theAlias to alias POSIX file "/"

 逆に、エイリアス値をパス文字列に変換することも可能です。
 パスを文字列として処理したいという事はよくあるので、しっかり覚えておいて下さい。
 POSIXパスを得る場合は次の通りです。

POSIX path of (alias "HD:テキスト:日記")
	--> "HD:テキスト:日記"

 さらに「=」や「/=」などの演算子でエイリアス値を比較したり、次のように「&」を使ってリストに追加することもできます。

set theList to {}
set theList to theList & (alias "HD:テキスト:日記:")

 Finder上で作成するエイリアスファイルはエイリアス値を記録しているファイルで、エイリアス値とは異なります(注1)。
 混乱しやすいので注意してください。
 本書ではファイルを「エイリアスファイル」、値を「エイリアス値」と呼んで区別します。

 別の環境にスクリプトをコピーした場合などは、流石にエイリアスも途切れます。
 公開するつもりのスクリプトならば、やはりファイル参照と同じように、ファイルが存在しない時の事を考えておく必要があります。

エイリアス値(HFSの場合)

 一応、HFSパスを使う場合についても書いておきます。
 エイリアス値は、次のように書きます(注1)。

alias "HD:テキスト:日記"

 as演算子を使って、HFSパス文字列をエイリアス値に変換する、という書き方もできます。

"HD:テキスト:日記" as alias

 逆にエイリアス値から、HFSパスを得る場合は次のように書きます。

(alias "HD:テキスト:日記") as text
	--> "HD:テキスト:日記"

POSIXと書式が異なっていて面倒くさい感じですが、書式を覚えておかなくても読む分にはすっと読めると思います。

パスの相互変換

 以上のように、現在OS X10.10では、ファイルの指定方法が入り乱れていて、場面(や単に個人的嗜好)によって使いやすい、あるいは関数によって必須の形式が存在します。
 そこで、ここではPOSIXパス文字列、HFSパス文字列、ファイル参照、エイリアス値の間の相互変換の方法を紹介します。
 一番汎用性が高い、POSIXパス文字列への、またPOSIXパス文字列からの変換という形で書きます。
 極力簡単な方法を取ったつもりですが、もしかしたらもっと簡単な方法があるかもしれません。

 まず、文字列、ファイル参照、エイリアス値の全てにPOSIX path属性が存在するので、これで簡単にPOSIXパス文字列に変換できます(注1)。

POSIX path of "HD:data:sample.txt"
	--> "/data/sample.txt"
POSIX path of file "HD:data:sample.txt"
	--> "/data/sample.txt"
POSIX path of alias "HD:data:sample.txt"
	--> "/data/sample.txt"

 POSIXパス文字列からファイル参照への変換は、ファイル参照とエイリアス値の書式で書いた通りですが、再度ここで書いておきます。

POSIX file "/data/sample.txt"
	--> file "HD:data:sample.txt"
alias POSIX file "/data/sample.txt"
	--> file "HD:data:sample.txt"

 さらにHFS文字列への変換はas演算子を使います。

POSIX file "/data/sample.txt" as text
	--> "HD:data:sample.txt"

 具体的な例を見てみましょう。
 次のスクリプトはchoose folder命令が返すエイリアス値を、POSIXパス文字列に変換し、その値をdo shell script命令に使ってlsコマンドを実行しています。

POSIX path of (choose folder)
do shell script "ls " & (quoted form of result)

 ここで登場したquoted form属性は、文字列を「 ' 」(クオート)で括るなどして、Shellのパスに合う形に変換してくれます。
 次のスクリプトを見ると、文字列内に含まれる「 ' 」がパスの終端と判定されないよう、加工されていることがわかるかと思います。

quoted form of "/that's"
 --> "'/that'\\''s'"

 do shell script命令とquoted form属性は、ほぼ間違いなく組み合わせて使われるので、ひとセットで覚えておくと良いでしょう。

path to 命令

 OSAXのpath to命令を使えば、主だったフォルダのエイリアス値を得ることができます。

 例えば、スクリプトを実行しているアプリケーション。

path to current application

 例えば、スクリプトファイル。(注1)。

path to me

 例えば、ホームフォルダ。
 以前「オブジェクトと属性」で、Finderの用語であるhomeを使いましたが、このpath to命令を使えば、Finderを使わずに、フォルダ位置を調べるられるわけです。

path to home folder

 path to命令には他にも、trash:ゴミ箱、sites folder:サイト、library folder:ライブラリ、documents folder:書類、services folder:サービス、Folder Action scripts:フォルダアクションスクリプト、scripts folder:スクリプト、など多くの定数が用意されています。
 詳しくは、path to命令に指定できる定数一覧をご覧ください。

 このpath to命令を使ってエイリアス値を得れば、起動ボリュームの名前が違ったり、ユーザー名が違ったりする環境でスクリプトを実行しても、それぞれのフォルダ位置を知ることができます。

 バンドル内に配置したファイルへのパスを得るには、path to resource命令(注2)を使います。
 次のスクリプトで、実行中のスクリプトバンドルに含まれる"Scripts"フォルダの"main.scpt"ファイルのエイリアス値を得ます。

path to resource "main.scpt" in directory "Scripts"

ファイルの読み書き

 では、指定したファイルを読み込んでみましょう。ファイルの読み込みは全く簡単です。
 OSAXのread命令を使うだけ。

 次のファイルは、ダイアログで指定したファイルを読み込んで、結果ウィンドウに表示します。
 一応、どんなファイルでも読み込む事はできますが、最初のうちはテキストファイル以外や、大きなサイズのファイルは読み込まない方がいいでしょう。

set theFile to choose file "ファイルを指定"
read theFile

 デフォルトでは、データは文字列として読み込まれますが、read命令にas引数をつける事で、どのようなデータ型で読み込むか指定できます。

 次は、データの保存です。同じくOSAX命令のwrite命令を使って、文字列をテキストファイルとして書き出します。
 新たにファイルを作る事はできませんので、適当なテキストファイルを事前に作っておいて下さい。
 また、確認なしに書き込むので、重要なファイルに上書きしないようにも気をつけて下さい。

set theFile to choose file "上書きするファイルを指定"
write "テストです" to theFile

 ただし、このスクリプトで上書きする場合に、前のファイルのデータが残ってしまう場合があります。
 新たに書き出したデータが、以前のデータよりも短い場合です。

 また、write命令もread命令と同じようにas引数でデータ型を指定する事ができます。

 これらの方法では、既に上げたように、いくつかの問題があります。
 さらに、ファイルの一部を読み込んだり、スクリプトで処理を行いつつ適宜書き込んだり、といったきめ細かな処理をする事はできません。
 さらに高度なファイル操作に付いては次回解説します。

【今回のまとめ】

POSIXパスは、

  • 項目名をスラッシュでつなぐ
  • POSIX fileでファイル参照に
  • POSIX path ofでPOSIXパス文字列に

HFSパスは、

  • 項目名をコロンでつなぐ
  • fileでファイル参照に
  • aliasでエイリアス値に

エイリアス値は、

  • ファイルに持たせる携帯電話
  • 「as」で文字列と相互変換
  • path to命令で様々なファイル・フォルダの値を得られる