UNIXの部屋 コマンド: ファイル制限まとめ


※空白区切りで AND 検索 (例:「ファイル 削除」)

用語集 ファイル制限まとめ UNIXにおけるファイル・ディレクトリについての規則・上限値のまとめ

ファイル名・ディレクトリ名の制限や、ファイル名の長さなどについて。

ファイル名で使用可能な文字
UNIX において、ファイル名として使用できない文字は以下の 2つのみである。
  • "/" (スラッシュ。ASCII コード 0x2F)
  • \0 (ASCII コードのゼロ)
上記以外の文字、例えば空白・タブ・各種記号 (#$%& など)・コントロールコードなどはすべて使用可能である。

実際に試してみよう。以下の Perl コマンドは、abc(0x01)(0x02)(0x03)..... というファイルを作成する。"....." の部分に \x04〜\xff まで入れてみて試してほしい (Perl における \xXX は 16進数を表す表記法である)。
% perl -MFcntl -e 'sysopen(FH, "abc\x01\x02\x03.....",O_WRONLY|O_CREAT, 0600)||die "$!"'

\x00 とスラッシュを表す \x2f を除く、\x01〜\x2e、\x30〜\xff すべての文字が使用可能であることが確認できるはずだ。
【注意】
ls コマンドはデフォルトではコントロールコードなどの表示できない文字を「?」で置き換えて表示する。実際のファイル名を確認したい場合は
% ls -w
とすることで、「?」への置換が行われなくなる。上記の実験の後にファイルを消したい場合、
% rm abc*
とワイルドカードを活用しよう。コントロールコードが多く含まれるため、コマンドラインからファイル名を正確に指定するのは結構難しい。

もしスラッシュを表す \x2f を入れると
% perl -MFcntl -e 'sysopen(FH, "abc\x01\x02\x03.....",O_WRONLY|O_CREAT, 0600)||die "$!"'
No such file or directory at -e line 1.
とエラーになる。これは、もし「ファイル名にスラッシュを含んでもよい」という仕様にした場合は、
% ls foo/bar.dat

  • 「foo」ディレクトリの下の bar.dat というファイル
と解釈すべきなのか、あるいは
  • 「foo/bar.dat」というファイル
と解釈すべきのか、という部分が曖昧になってしまうための制限である。

また、\x00 を入れるとそこが文字終端として扱われるので、
% perl -MFcntl -e 'sysopen(FH, "abc\x00def",O_WRONLY|O_CREAT, 0600)||die "$!"'
としても abc というファイルが作成される。Perl における sysopen はシステムコール open(2) を呼び出すだけだが、open(2) は「引数で指定されたアドレスから、0x00 が出現するまでの文字列」をファイル名と見なすため、open(2) からすると
"abc"

"abc\0def"
の区別がつかない。よって、より正確に言うと、「ファイル名の終端を表すコードが \0 であるため、ファイル名に \0 を渡しても、そこがファイル名の終端と見なされてしまい、結果的にファイル名に \0 を含めることができない」となる。

. と .. と /
"." はカレントディレクトリを表す。".." は親ディレクトリ (1階層あがったディレクトリ) を表す。これは、表記法ではなく、実際にあらゆるディレクトリに "." と ".." というディレクトリエントリが存在する。"." と ".." はファイル名としては正しいが、どのディレクトリにも既に作成されているため、新たに作成することはできない。

なお、ルートディレクトリ ("/") にも親ディレクトリ ".." は存在するが、「ルートディレクトリの親ディレクトリはルートディレクトリ」("/.." は "/" は同一) と定義されている。

"/" は、パス名の先頭であればルートディレクトリを現し、パス名の途中に現れればディレクトリの区切りを表す。
/foo
⇒ ルートディレクトリ直下の foo というファイル (またはディレクトリ)
/foo/bar
⇒ ルートディレクトリ直下の foo というディレクトリの下の bar というファイル (またはディレクトリ)
foo/bar
⇒ カレントディレクトリ直下の foo というディレクトリの下の bar というファイル (またはディレクトリ)
"//" や "////" のようにスラッシュを連続して記述しても、"/" と同じものとして扱われる (POSIX で定義されている)。

拡張子
MS-DOS や Windows では拡張子は OS と密接に連携しており、例えばファイルのダブルクリック時に拡張子を元に関連付けの定義を参照し、起動すべきアプリケーションを決定する。しかし UNIX における拡張子はより緩いルールのようなものにすぎず、OS レベルでは拡張子を意識することはない。

とはいえ、gcc などのコンパイラにおいては
foo.c → foo.s → foo.o → foo
と拡張子が順に変わっていくし、make コマンドもコンパイル支援を行うのが主目的であるためサフィックスルールを実装している。このように、いくつかのコマンドは拡張子と密接に関係している。

ファイル名の長さ制限(ファイル名最大長)
多くの UNIX 系 OS においては、ファイル名の長さの上限は 255バイトである。
% touch 1234567890(以下、あわせて25回繰り返し)12345
⇒ 255文字のファイル作成は成功
% touch 1234567890(以下、あわせて25回繰り返し)123456
touch: File name too long
⇒ 256文字は失敗

ただしこれは、あるディレクトリエントリ内の文字列長の上限が 255バイトである、というだけで、パス全体の合計が 255バイトを超える分には問題ない。つまり、
/too/long/long/long/long/long/...(略).../long/filename
は、"/too" から "/filename" までを 255文字以内にする必要はない (ただし、パス全体の長さ制限はある。後述)。なお、「255文字」ではなく「255バイト」であることに注意。Shift_JIS や EUC-JP などで日本語ファイル名を作成する場合、2〜3バイトで1文字を構成するため、日本語使用時は120文字程度しか使用できないことになる。

ちなみに古い UNIX では 14バイトであったが、おそらく 4.2BSD の FFS 実装において 255バイトに拡張されたと思われる。

パスの長さ制限(パス名最大長)
多くの UNIX 系 OS においては、パス名全体の長さの上限は 1023バイトである。これは
/too/long/long/long/long/long/...(略).../long/filename
の "/too" から "/filename" までの長さである。ただし、これはファイルシステムの制限ではなく、システムコールに与えるパス名の長さの上限であることに注意すること。つまり、
% ls /too/long/long/long/long/...(略).../long/filename
ls: File name too long
は長すぎるのでエラーとなったとしても、以下のように cd コマンドでディレクトリを少しずつ降りていき、一度に 1023バイトを超えないようにすれば問題ない (FreeBSD 5.2.1-RELEASE にて実験済)。
% cd /too/long/long/long/long/long
% cd long/long/long/long/long
% (略)
% cd long/long/long/long/long
% ls filename

とはいえ、当然ながら扱いづらいことに変わりはないため、あまりに長い文字列は使用しないことをお勧めする。

ファイル・ディレクトリ数の上限
ひとつのディレクトリ直下に格納できる、ファイル・ディレクトリ数については、おそらく上限はない。おそらく、数万・数十万のファイルを同一ディレクトリ内に作成することは可能であろう。ただし、少なくとも UFS (FFS/FFFS)・ext2・ext3 においてはファイル名の探索は線形探索であり、非常に遅い。具体的には、特定のファイルをオープンしたり、タイムスタンプやパーミッションなどの情報を得る (stat(2)) 場合などは、そのディレクトリ内のエントリを 1つずつ順に調べ、一致するファイル名を探し出す必要がある。

現実的には、ひとつのディレクトリに数万〜数十万のファイルを置くと、ls -l の結果を見るだけでそれなりに時間がかかるようになる。ひとつのディレクトリに置くファイルは、多くても 1000個程度にとどめておくことをお勧めする (ちなみに RaiserFS・xfs・jfs などのイマドキなファイルシステムでは、B+-Tree や B*-Tree などの二分木を発展させた管理方法を採用しており、ファイル数の増加はそれほど問題にはならない)。

なお、ファイルシステム全体としては i-node (inode) の数がファイル・ディレクトリ数の上限である。i-node の使用数・未使用数は df コマンドに -i オプションを渡すことで確認できる。
% df -i
Filesystem  1K-blocks     Used     Avail Capacity iused    ifree %iused  Mounted on
/dev/ad0s1a    253678    39866    193518    17%    1040    31982    3%   /
/dev/ad0s1e    253678     2152    231232     1%     254    32768    1%   /tmp
/dev/ad0s1f 186444376 39519590 132009236    23% 5528815 18564879   23%   /usr
詳細は df コマンドを参照。

i-node 数の上限は UFS (FFS/FFFS)・ext2・ext3 などの古めのファイルシステムであっても 2^32 個 (42億) であるため、現実的には問題になることは少ないだろう。

余談
当ページ管理人が 2006年ごろ、ひとつのディレクトリに数万個のファイルを作成してみたことがあったのだが、ls しようとすると bash がコアダンプしてしまった (Fedora Core 3 + bash)。また、これは2000年ごろだと思うが、数万階層のディレクトリを作成したら消せなくなったことがある (FreeBSD)。また、gzip のようにファイルサイズ 2GB や 4GB で問題が発生するコマンドもある。

ファイルシステムの仕様上は問題ないとしても、OS のバグ・周辺アプリケーションのバグを踏む可能性があるので、クリティカルなシステムにおいてあまり冒険するのは避けた方がよいだろう。


頑張って書いたおすすめコンテンツ!