拡張子にはピリオドを含むのか?という話


Windows 95(日本語版)が発売されたのはちょうど15年前の今日、11月23日である。Windows 95ではロングファイルネームが採用された。これに伴い、拡張子が再解釈された。それまでは拡張子と言えば3文字までであったが、Windows 95では3文字を超える拡張子が使えるようになった。また、ピリオドも拡張子に含まれると考えられるようになった。[要出典]


今日は、この問題について少し掘り下げて考えてみよう。


いまどき「拡張子」と言うとピリオドも含む("txt"ではなく、".txt"のように)と私は思う。しかし、時として次のような説明を見かける。

ファイル名のうち、「.」(ピリオド)で区切られた一番右側の部分。例えば、ファイル名が「e-words.txt」ならば「txt」が拡張子である。


IT用語辞典
http://e-words.jp/w/E68BA1E5BCB5E5AD90.html

これだと"e-words."が拡張子を除くファイル名だということになってしまう。あなたはメモ帳でテキストファイルを保存するときに"e-words."という名前を入れたのか?最後のピリオドは入れてないだろう。つまり、拡張子として付与されたのは".txt"である。このことからも拡張子はピリオドを含むと考えるほうが自然なのだ。


話を戻して、どうして上のIT用語辞典のような説が広まってしまったのか考えてみる。


思えば、MS-DOSやWindows 3.1のころは、ファイル名は8文字、拡張子は3文字固定であった。これは8.3形式と呼ばれた。


このときファイル名(8文字)と拡張子(3文字)との間にあるピリオドは、頼んでもいないのに勝手についてくる居酒屋のお通しみたいな存在だった。


このピリオドがファイル名に属するのか拡張子に属するのかは誰にもよくわかっていないところがあった。またこのピリオド自体、ファイルシステム上には記録していなかった。要するにdirコマンドで表示させたときに便宜上ついてくるだけで、実際にはどこにも存在しないものだった。


8.3形式の起源をさらに遡れば、CP/Mに行き着く。CP/Mは、MS-DOSの前身であるQDOSが規範としたOSだ。(正確には規範というか、QDOSはCP/Mのパチもんそのものだったのだが…、まあ、それはそれとして…。) それゆえMS-DOSとの類似点が多い。私はCP/Mのフロッピーディスクをセクターダンプしたことがあるが、ファイル名のところにピリオドは含まれてなかったと思う。


CP/Mで採用された8.3形式のアイデアは、何もCP/Mがオリジナルというわけではなく、それより先にRT-11というリアルタイムOSが6.3形式(ファイル名6文字+拡張子3文字)をサポートしている。(RT-11が誕生したのは1970年だとされる) これがDECマシンに採用され出して1975年ぐらいにはそこそこ大学なんかには普及してたのだと思うけど、当時のDECマシンのことは私は伝え聞きでしかないのでよくわからない。


RT-11で採用された6.3形式が内部的に(ファイルシステム上)、ピリオドは保有していなかったことはMS-DOSやCP/Mの例からも想像に難くない。すなわち9バイトなのだ。9は2の累乗ではない。とても不自然な数字だ。16なら歯切れがいいのに、9や11だなんて、16バイトにしようと思うと余るのだが、残りはどこに行ってしまったのか?


MS-DOSの8.3形式の内訳については
http://en.wikipedia.org/wiki/8.3_filename
に書いてある。8.3形式で11バイト、あとファイル属性やらタイムスタンプやら何やらで32バイトになってキリが良いようだ。


RT-11のほうはこの部分の説明がなくてよくわからない。
http://en.wikipedia.org/wiki/RT-11


だがしかし、どうも6.3形式は9文字だから文字をpackすると6バイトに収まるのだそうだ。んー、待てよ。アルファベットと数字だと36文字。32文字は超えているので5-bitに収まらん。6-bitだとすると、6-bit×9文字 = 54 bits > 6 bytes。うーん。6バイト超えてますけど。使ってないbitを切り詰めるような単純なpackではないようだ。


仮にアルファベットと数字とスペースなどのいくつかの記号で40文字あったとして、9桁の40進数とみなせば、40進**9桁 < 256**6文字 < 41進**9桁 ("**"は累乗を意味する。)で40文字ならちょうど収まり、41文字だと収まらないというわけですか。ということで、RT-11はたぶん(スペース、改行コードなどを含めて)40種類の文字がファイル名に使えたのだろうと推測しますた。


あと、残りの2バイトとして年月日を示すタイムスタンプがあって、これで8バイトですかね。タイムスタンプは年が7bit、月が4bit、日が5bitと相場がきまっちょります。(例:MS-DOSでは年の部分が0なら1980年を意味して、127なら2107年を意味する。MS-DOSで2107年より未来のタイムスタンプに出来ないのはこのため)


まあ何にせよ、このように6.3形式のファイル名を1バイトすらもったいないからと涙ぐましい努力で6バイトにpackしていたRT-11において、拡張子のピリオドが内部的に(外部ストレージ上に)保有されていないことは自明だ。


とまあ、以上の考察でわかったように、RT-11で拡張子が採用された時からCP/M(≒QDOS)を経て MS-DOS , Windows 3.1に至るまでピリオドは特別扱いされてきたという歴史的な経緯がある。それがWindows 95になって、ロングファイルネームが採用されたときにこの特別扱いが無くなり、ピリオドは拡張子として含まれるという風に再解釈されたのではないかと私は思う。(→ 詳しくはコメント欄に…。)


ところが、これがMS-DOS時代からプログラムを書いているプログラマにはまだこれが十分に認識されていなくて、例えば、.NET FrameworkのPath.GetExtension()では".txt"のようにピリオドを含めて返ってくるのに"txt"が返ってくるのだと勘違いしてプログラムを書いてしまうことがある。おい、Windows 95が出てからもう15年も経ってるんだぞ!いまどきピリオドも拡張子に含むんだ。そろそろ覚えとくれ。