ファイル、パス、名前空間の名前付け

Windows でサポートされているすべてのファイル システムは、ファイルとディレクトリの概念を使って、ディスクまたはデバイスに格納されたデータにアクセスします。 ファイルとデバイスの入出力のための Windows API を使う Windows 開発者は、ファイルとディレクトリの名前に関するさまざまな規則、規約、制限を理解している必要があります。

データには、ファイル I/O API を使ってディスク、デバイス、ネットワーク共有からアクセスできます。 ファイルとディレクトリは、名前空間と共にパスの概念の一部です。ディスク、デバイス、ネットワーク接続のいずれかに関係なく、特定の操作対象のデータを取得する場所を文字列で表現したものです。

NTFS などの一部のファイル システムは、リンクされたファイルとディレクトリをサポートしており、通常のファイルやディレクトリと同様のファイルの名前付け規則と他の規則に従います。 詳細については、「ハード リンクとジャンクション」と「再解析ポイントとファイル操作」を参照してください。

長いファイル パスをサポートするように Windows を構成する方法については、「パスの最大長の制限」を参照してください。

ファイルとディレクトリの名前

すべてのファイル システムは、個々のファイルに対して同じ一般的な名前付け規則に従っています。つまり、ベース ファイル名と省略可能な拡張子をピリオドで区切ったものです。 ただし、NTFS、CDFS、exFAT、UDFS、FAT、FAT32 などの各ファイル システムには、ディレクトリやファイル パスの各コンポーネントの形式について固有の異なる規則が存在する場合があります。 "ディレクトリ" は、ディレクトリであると指定する特殊な属性を持つ単なるファイルですが、それを除くと、通常のファイルと同じ名前付けルールに従う必要があることに注意してください。 ファイル システムに関する限り、用語 "ディレクトリ" は単に特殊な種類のファイルを指すので、参考資料によっては、ディレクトリとデータ ファイルの両方の概念を包含する一般的な用語 "ファイル" を使う場合があります。 このため、特記がない限り、ファイルの名前付けと使用のルールと例はディレクトリにも適用されると考えられます。 用語 "パス" は、1 つ以上のディレクトリ、バックスラッシュ、場合によってはボリューム名を指します。 詳細については、「パス」セクションを参照してください。

文字数の制限も異なる場合があり、使うファイル システムやパス名のプレフィックス形式に応じて異なる場合があります。 下位互換性メカニズムをサポートする場合、これはさらに複雑になります。 たとえば、以前の MS-DOS FAT ファイル システムは最大 8 文字のベース ファイル名、最大 3 文字の拡張子、ドット区切り記号を含めて合計 12 文字をサポートします。 これは一般に "8.3 ファイル名" と呼ばれます。 Windows の FAT と NTFS のファイル システムは "長いファイル名をサポート" するので、8.3 ファイル名に制限されませんが、8.3 バージョンの長いファイル名も引き続きサポートしています。

命名規則

次の基本的な規則により、アプリケーションはファイル システムに関係なく、ファイルとディレクトリに有効な名前を作成し、処理することができます。

  • ディレクトリまたはファイルの名前に含まれるベース ファイル名と拡張子を区切るには、ピリオドを使います。

  • "パス" の "コンポーネント" を区切るには、バックスラッシュ (\) を使います。 バックスラッシュを使って、ファイル名とそのパスの間と、パス内の 1 つのディレクトリ名と別のディレクトリ名の間を分割します。 バックスラッシュは、名前を複数のコンポーネントに区切る予約文字なので、実際のファイルやディレクトリの名前に使うことはできません。

  • バックスラッシュはボリューム名の一部として必要に応じて使います。たとえば、"C:\path\file" に含まれる "C:\" や、汎用名前付け規則 (UNC) の名前の "\\server\share\path\file" に含まれる "\\server\share" です。 UNC 名の詳細については、「パスの最大長の制限」セクションを参照してください。

  • 大文字と小文字の区別は想定しないでください。 たとえば、OSCAR、Oscar、oscar は、ファイル システム (POSIX 準拠のファイル システムなど) によっては異なるものと見なされますが、同じ名前であると考えてください。 NTFS は大文字と小文字を区別する POSIX セマンティクスをサポートしていますが、これは既定の動作ではないことに注意してください。 詳細については、CreateFile のページを参照してください。

  • ボリューム指定子 (ドライブ文字) も同様に大文字と小文字が区別されません。 たとえば、"D:\" と "d:\" は同じボリュームを指します。

  • 名前には、Unicode 文字や拡張文字セット (128 から 255) の文字を含め、現在のコード ページ内の任意の文字を使います。ただし、以下を除きます。

    • 以下の予約文字:

      • < (より小さい)
      • > (より大きい)
      • : (コロン)
      • " (二重引用符)
      • / (スラッシュ)
      • \ (円記号)
      • | (縦棒またはパイプ)
      • ? (疑問符)
      • * (アスタリスク)
    • 整数値のゼロ。ASCII NUL 文字とも呼ばれます。

    • 整数表現の 1 から 31 の範囲にある文字。ただし、これらの文字が許可されている代替データ ストリームは除きます。 ファイル ストリームの詳細については、「ファイル ストリーム」を参照してください。

    • ターゲット ファイル システムで許可されていないその他の文字。

  • 現在のディレクトリを表すには、パスのディレクトリ "コンポーネント" としてピリオドを使います (例: ".\temp.txt")。 詳細については、「パス」を参照してください。

  • 現在のディレクトリの親を表すには、パスのディレクトリ "コンポーネント" として連続する 2 つのピリオド (..) を使います (例: "..\temp.txt")。 詳細については、「パス」を参照してください。

  • ファイルの名前に次の予約名は使わないでください。

    CON、PRN、AUX、NUL、COM0、COM1、COM2、COM3、COM4、COM5、COM6、COM7、COM8、COM9、COM¹、COM²、COM³、LPT0、LPT1、LPT2、LPT3、LPT4、LPT5、LPT6、LPT7、LPT8、LPT9、LPT¹、LPT²、LPT³。 また、これらの名前の直後に拡張子を付けないでください。たとえば、NUL.txt と NUL.tar.gz はどちらも NUL と同じです。 詳細については、「名前空間」を参照してください。

    Note

    Windows では、8 ビット ISO/IEC 8859-1 上付き数字 ¹、²、および ³ が数字として認識され、COM# および LPT# デバイス名の有効な部分として扱われるため、すべてのディレクトリで予約されています。 たとえば、echo test > COM¹ でファイルの作成に失敗します。

  • ファイルやディレクトリの名前の末尾をスペースまたはピリオドにしないでください。 基となるファイル システムがこのような名前をサポートしているとしても、Windows のシェルとユーザー インターフェイスではサポートされません。 ただし、名前の最初の文字にピリオドを指定することはできます。 たとえば、".temp" です。

短い名前と長い名前

長いファイル名とは、短い MS-DOS (8.3 とも呼ばれます) スタイルの名前付け規則を超えるファイル名と考えられます。 長いファイル名を作成した場合、Windows によって "8.3 エイリアス" (つまり短い名前) という短い 8.3 形式の名前も作成し、ディスクに格納することもできます。 特定のファイル システムに応じて、システム全体または特定のボリュームのパフォーマンス上の理由からこの 8.3 エイリアシングを無効にすることができます。

Windows Server 2008、Windows Vista、Windows Server 2003、Windows XP: Windows 7 と Windows Server 2008 R2 までは、特定のボリュームに対して 8.3 エイリアシングを無効にすることはできません。

多くのファイル システムでは、ファイル名の中で、長すぎて 8.3 名前付けルールに準拠できない各コンポーネント名にはチルダ (~) が含まれます。

Note

すべてのファイル システムがチルダ置換規約に従っているわけではありません。通常はサポートしていても、8.3 エイリアス生成を無効にするようにシステムが構成されている可能性があります。 そのため、8.3 エイリアスが既にディスク上に存在することを前提としないでください。

システムから 8.3 ファイル名、長いファイル名、またはファイルの完全なパスを要求するには、次のオプションを検討してください。

  • 長いファイル名の 8.3 形式を取得するには、GetShortPathName 関数を使います。
  • 短い名前の長いファイル名バージョンを取得するには、GetLongPathName 関数を使います。
  • ファイルの完全なパスを取得するには、GetFullPathName 関数を使います。

NTFS、exFAT、UDFS、FAT32 などの新しいファイル システム上では、Windows によって Unicode の長いファイル名がディスクに格納されます。つまり、元の長いファイル名が常に保持されます。 これは、ディスクの読み取りまたは書き込み操作中にアクティブになるコード ページに関係なく、長いファイル名に拡張文字が含まれている場合にも当てはまります。

長いファイル名を使うファイルは、ファイル名情報を失うことなく、NTFS ファイル システム パーティションと Windows FAT ファイル システム パーティション間でコピーできます。 実際のファイル名によって異なりますが、以前の MS-DOS FAT や一部の種類の CDFS (CD-ROM) ファイル システムはそうではない場合があります。 この場合、可能であれば短いファイル名に置き換えられます。

パス

特定のファイルの "パス" は、特殊文字 (バックスラッシュ) で区切られた 1 つ以上の "コンポーネント" から構成されます。通常、各コンポーネントはディレクトリ名またはファイル名ですが、後述するように注意が必要な例外もあります。 多くの場合、システムがパスを解釈する際にパスの先頭 (つまり "プレフィックス") が何であるかが重要です。 このプレフィックスによって、パスが使っている "名前空間" と、さらには (末尾の文字を含む) パス内のどの位置にどの特殊文字が使われるかが決まります。

パスのコンポーネントがファイル名である場合、最後のコンポーネントにする必要があります。

パスの各コンポーネントは、特定のファイル システムに指定された最大長の制約も受けます。 一般に、これらの規則は "短い" と "長い" という 2 つのカテゴリに分類されます。 ディレクトリ名は特殊な種類のファイルとしてファイル システムに格納されますが、ファイルの名前付けルールはディレクトリ名にも適用されることに注意してください。 要約すると、パスとは、特定のファイル名またはディレクトリ名に対して存在するすべてのディレクトリ間の階層を単に文字列で表現したものです。

完全修飾と相対パス

ファイルを操作する Windows API 関数の場合、ファイル名は現在のディレクトリからの相対パスで示すことがよくありますが、一部の API では完全修飾パスが必要です。 ファイル名が次のいずれかで始まらない場合は、現在のディレクトリからの相対パスです。

  • 任意の形式の UNC 名。常に 2 つのバックスラッシュ文字 ("\\") で始まります。 詳細については、次のセクションを参照してください。
  • バックスラッシュを含むディスク指定子。たとえば、"C:\" や "d:\"。
  • バックスラッシュ 1 つ。たとえば、"\directory" または "\file.txt"。 これは "絶対パス" とも呼ばれます。

コロンの後のバックスラッシュを含まないディスク指定子のみでファイル名が始まる場合、指定した文字のドライブ上にある現在のディレクトリへの相対パスであると解釈されます。 現在のディレクトリがルート ディレクトリかどうかは、そのディスクに対して行われた最新の "ディレクトリの変更" 操作による設定内容に応じて変わることに注意してください。 この形式の例を以下に示します。

  • "C:tmp.txt " は、C ドライブの現在のディレクトリにある "tmp.txt " というファイルを指します。
  • "C:tempdir\tmp.txt" は、C ドライブの現在のディレクトリのサブディレクトリにあるファイルを指します。

パスに "二重ドット" が含まれる場合にも相対パスと呼ばれます。つまり、パスのいずれかのコンポーネントに 2 つの連続するピリオドが含まれている場合です。 この特殊な指定子は、現在のディレクトリの上にあるディレクトリ ("親ディレクトリ" とも呼ばれます) を示すために使われます。 この形式の例を以下に示します。

  • "..\tmp.txt" は、現在のディレクトリの親ディレクトリにある tmp.txt というファイルを示します。
  • "..\..\tmp.txt" は、現在のディレクトリの 2 つ上のディレクトリにあるファイルを示します。
  • "..\tempdir\tmp.txt" は、現在のディレクトリのピア ディレクトリである tempdir というディレクトリにある tmp.txt というファイルを示します。

相対パスは、"C:..\tmp.txt" のように、両方の例を組み合わせることができます。 これが便利である理由は、現在のドライブとしてどのドライブ指定子が設定されているかに関係なく、システムは現在のドライブとそのドライブの現在のディレクトリを共に追跡し、さらに各ドライブ文字 (システムに複数ある場合) の現在のディレクトリも追跡しているからです。

パスの最大長の制限

Windows 10 バージョン 1607 より前のエディションでは、パスの最大長は MAX_PATH であり、260 文字と定義されています。 それ以降のバージョンの Windows でこの制限を削除するには、レジストリ キーを変更するか、グループ ポリシー ツールを使う必要があります。 詳細については、「パスの最大長の制限」を参照してください。

名前空間

Windows API で使われる名前空間規約には主に 2 つのカテゴリがあり、一般に "NT 名前空間" と "Win32 名前空間" と呼ばれます。 NT 名前空間は、Win32 サブシステムと、拡張機能による Win32 名前空間を含め、他のサブシステムと名前空間が存在する可能性がある最も低いレベルの名前空間として設計されました。 POSIX は、NT 名前空間の上に構築された Windows のサブシステムの一例です。 Windows の初期バージョンには、通信 (シリアルと並列) ポートや既定のディスプレイ コンソールなどの特定の特殊デバイスに対し、現在は NT デバイス名前空間と呼ばれるものの一部として事前定義済みまたは予約済みの名前もいくつか定義されていました。これは下位互換性のために現在のバージョンの Windows でもサポートされています。

Win32 ファイルの名前空間

Win32 名前空間のプレフィックスと規約について、このセクションと次のセクションにまとめ、その使用方法について説明します。 ここで示す例は Windows API 関数での使用を想定しています。エクスプローラーなどの Windows シェル アプリケーションで必ずしも機能するわけではありません。 このため、Windows シェル アプリケーションから通常使用できるパスよりも広い範囲を使用できます。また、これを活用する Windows アプリケーションは、これらの名前空間規約を使って開発できます。

ファイル I/O でパス文字列に "\\?\" というプレフィックスを付けると、文字列の解析を無効にし、それに続く文字列をそのままファイル システムに送信するように Windows API に指示できます。 たとえば、ファイル システムが長いパスとファイル名をサポートする場合、Windows API によって適用される MAX_PATH 制限を超える可能性があります。 通常のパスの最大長の制限については、前のセクションの「パスの最大長の制限」を参照してください。

パス文字列の自動展開はオフなので、"\\?\" プレフィックスを指定して、".." と "." を使うこともできます。これが便利なのは、完全修飾パスの一部に予約済み相対パス指定子を使い、ファイルに対して操作を実行する場合です。

すべてではありませんが、多くのファイル I/O API は "\\?\" をサポートしています。各 API のリファレンス トピックを参照して確認することをお勧めします。

Unicode API を使用して、「\\?\」プレフィックスで MAX_PATH を超過できるようにする必要があることに注意してください。

Win32 デバイスの名前空間

"\\.\" プレフィックスを指定すると、Win32 ファイル名前空間ではなく、Win32 デバイス名前空間にアクセスします。 これは、ファイル システムを介さずに物理ディスクやボリュームに直接アクセスする方法です (ただし API がこの種のアクセスをサポートしている場合)。 この方法でディスク以外の多くのデバイスにアクセスできます (たとえば CreateFileDefineDosDevice 関数を使います)。

たとえば、システムのシリアル通信ポート 1 を開く場合、CreateFile 関数の呼び出しで "COM1" を使用できます。 これが機能するのは、COM1 から COM9 が NT 名前空間の予約名に含まれているからです。ただし、これらのデバイス名に "\\.\" プレフィックスを使っても機能します。 一方、100 ポート シリアル拡張ボードを搭載し、COM56 を開く場合、COM56 には事前に定義された NT 名前空間がないため、"COM56" を使って開くことはできません。 開くには "\\.\COM56" を使う必要があります。なぜなら、"\\.\" を使うと、事前に定義されたエイリアスが特定されるのではなく、デバイス名前空間に直接移動されるからです。

Win32 デバイス名前空間を使うもう 1 つの例は、CreateFile 関数に "\\.\PhysicalDriveX" (X は有効な整数値) または "\\.\CdRomX" を使う場合です。 この方法でファイル システムをバイパスし、これらのデバイスに直接アクセスできます。 これが機能するのは、これらのデバイスが列挙されるときに、これらのデバイス名がシステムによって作成されるからです。ドライバーによっては、システム内に他のエイリアスも作成されます。 たとえば、"C:\" という名前を実装しているデバイス ドライバーには、ファイル システムでもある独自の名前空間があります。

CreateFile 関数を使う API には一般に "\\.\" プレフィックスを使用できます。CreateFile 関数は、使うパラメーターに応じてファイルとデバイスの両方を開くために使われる関数だからです。

Windows API 関数を使う場合は、ファイルではなくデバイスにアクセスする場合にのみ "\\.\" プレフィックスを使ってください。

ほとんどの API は "\\.\" をサポートしません。デバイス名前空間を使用できるように設計されている場合にのみ、認識されます。 必ず各 API のリファレンス トピックを確認してください。

NT 名前空間

NT 名前空間規約を使用できる API もありますが、Windows オブジェクト マネージャーを使うと、ほとんどの場合は不要になります。 たとえば、Windows Sysinternals WinObj ツールを使って、システム オブジェクト ブラウザーで Windows 名前空間を参照すると便利です。 このツールを実行すると、ルートまたは "\" で始まる NT 名前空間が表示されます。 "Global??" というサブフォルダーは Win32 名前空間が存在する場所です。 名前付きデバイス オブジェクトは NT 名前空間の "Device" サブディレクトリ内に存在します。 また、お使いのシステム上に複数の COM ポートがある場合、最初の 2 つを表すデバイス オブジェクトとして Serial0 と Serial1 があるとします。 ボリュームを表すデバイス オブジェクトは、数字のサフィックスは異なるかもしれませんが、"HarddiskVolume1" などです。 サブディレクトリ "Harddisk0" の下にある "DR0" という名前は、たとえばディスクを表すデバイス オブジェクトです。その他も同様です。

これらのデバイス オブジェクトを Windows アプリケーションからアクセスできるようにするために、デバイス ドライバーは Win32 名前空間である "Global??" に、それぞれのデバイス オブジェクトに対するシンボリック リンク (symlink) を作成します。 たとえば、"Global??" サブディレクトリの下にある COM0 と COM1 は単に Serial0 と Serial1 に対するシンボリック リンク、"C:" は HarddiskVolume1 に対するシンボリック リンク、"Physicaldrive0" は DR0 に対するシンボリック リンクなどです。 シンボリック リンクがなければ、指定したデバイス "Xxx" は、前述のように Win32 名前空間規約を使う Windows アプリケーションから使用できません。 ただし、"\Device\Xxx" 形式の NT 名前空間の絶対パスをサポートする任意の API を使って、そのデバイスに対するハンドルを開くことができます。

ターミナル サービスや仮想マシンでマルチユーザーがサポートされるようになり、システム全体のルート デバイスを Win32 名前空間内に仮想化することがさらに必要になりました。 これは、Win32 名前空間に "GLOBALROOT" というシンボリック リンクを追加することで実現しました。これは、前述した WinObj ブラウザー ツールの "Global??" サブディレクトリで確認できます。また、パス "\\?\GLOBALROOT" を使ってアクセスできます。 このプレフィックスを使うと、それに続くパスで、セッション依存のパスではなく、システム オブジェクト マネージャーの真のルート パスを確実に検索できます。

関連項目