ファイル名で使えない文字
イントロ
web アプリケーションで、ユーザーにファイルをダウンロードさせる機能を追加したいとする。
例えばダウンロードさせるファイルの名前をアプリ側で自動決定する場合、その名前にはどのような制限があるのだろうか。
何回か調べてる気がするので、まとめてみる。
前提
そもそも、ファイル名の制限は、OS ではなく、基本的にはファイルシステムで決まる。
ファイルシステム上の限界
ファイルシステムの限界はどこまでなのかというと Comparison of file systems - Wikipedia, the free encyclopedia にまとめられている。
古いファイルシステムでは、ファイル名は 8 文字、拡張子が 3 文字、ドットも含めて合計 12 文字までしかダメ、という時代もあったらしい。8.3形式
と呼ばれているのがそれだ。
有名どころのファイルシステム(NTFS
, FAT系
, ext4
, xfs
)では
という仕様が多いようだ。
Windows で禁止されている予約語
ただし Windows は例外がある。
ファイルシステムだけでなく、OS レベルで予約されている文字があり、これらはファイル名として使えない。
Naming Files, Paths, and Namespaces (Windows) によると、以下の文字が予約されている。
< (less than) > (greater than) : (colon) " (double quote) / (forward slash) \ (backslash) | (vertical bar or pipe) ? (question mark) * (asterisk)
手元に win 機が無かったので、残念ながら検証はしていない。
本当にダメなのか試してみたい。
結論
対応するファイルシステムのカバー範囲により、ファイル名に使える文字は異なる。
だが、現実的な落とし所として
- windows を視野にいれるのであれば、windows で禁止されている予約語は使わないほうが良いと思う。
- 予約語 is
< > : " / \ | ? *
- 予約語 is
- NULL文字も使えないファイルシステムが多いため、止めたほうが無難。
- 長過ぎるファイル名は NG なので、そのあたりも調整する。
- マルチバイト文字のときが面倒くさいが、より小さい方に合わせ
255 byte まで
のほうががいいのかな。
- マルチバイト文字のときが面倒くさいが、より小さい方に合わせ
ぐらいを考えておけば良さそうだろうか。
おまけ
https://en.wikipedia.org/wiki/Comparison_of_file_systems によると、制限は以下の通り
File system | Maximum filename length | Allowable characters in directory entries | Maximum pathname length | Maximum file size | Maximum volume size |
---|---|---|---|---|---|
HFS Plus | 255 UTF-16 characters | Any valid Unicode | Unlimited | slightly less than 8 EiB | slightly less than 8 EiB |
# 制御文字のファイル名は作れる `touch "\a"` => "" # null 文字はダメだった `touch "\x0"` # ArgumentError: string contains null byte # from (irb):1:in ``' # from (irb):1 # from /Users/argerich/.rbenv/versions/2.3.0/bin/irb:11:in `<main>' # 256 byte は長すぎる `touch #{"a" * 256}` touch: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: File name too long # 255 byte なら OK `touch #{"a" * 255}` => "" # 日本語で 255 文字はアウト `touch #{"あ" * 255}` touch: あああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ: File name too long >> "あ".bytesize => 3 # 3 * 85 = 255 なので、85 文字まで OK >> `touch #{"あ" * 85}` => "" # 86 文字目からアウト >> `touch #{"あ" * 85 + "a"}` touch: あああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああa: File name too long # UTF-16 が OK ならば、絵文字でもいけるはず。 `touch #{"\u{26C4}" * 85}` => ""
絵文字ファイル名で作れているっぽい。ls
すると ?
になるけど。
それにしてもWikipedia 先生。ファイル名の長さ、255 byte までなのでは?
Any valid Unicode
の中に null 文字は入ってないのかな?
一部の文字は互換性維持のため、OS の API で制御しているとの噂もあるけど… うーむ。
情報が少なすぎて、これ以上調べるのは難しそうだった。一次情報どこにあるの。
試してみたものの、Wikipedia を引用してまとめたので、すごい微妙になってきた…
この記事は用法用量を守って、正しくお使いください。