Windowsにはファイル名やフォルダー名に「使えない」文字がある。しかし実際には、これ以外にも「使わないほうがいい」文字がある。今回は、そうした文字について考えてみる。
Windowsのファイル名やフォルダー名を一括して「パス名」とする。パス名には、ファイル名とフォルダー名、パス区切り文字が含まれている。パス名に使えない文字は、場所によっても異なる。たとえば、ファイルシステムに対するAPIで扱うパスなのか、アプリケーションが扱うパスなのか、コマンドラインのパスなのかで違いがある。しかし、ファイル名/フォルダー名には、パス区切り文字は入れることができない。標準では円マーク(逆スラッシュ)とスラッシュがパス区切り文字になっている。
Windowsでファイル名に「使ってはいけない」文字
Windowsには、ファイル名やフォルダー名に「使うことができない」文字があり、ファイル名を変更するとき、これらの文字が入ると警告を表示して、不可能であることを教えてくれる。それは以下の表のの9つの文字だ。
文字 | 名称 | 意味 |
---|---|---|
\ | 円マーク | パスの区切り記号 |
⁄ | スラッシュ | パスの区切り記号 |
: | コロン | ドライブ文字記号 |
* | アスタリスク | ワイルドカード記号 |
? | 疑問符 | ワイルドカード記号 |
" | 2重引用符 | パスを囲む |
> | 大なり不等号 | リダイレクト記号 |
< | 小なり不等号 | リダイレクト記号 |
| | 縦棒、バー | パイプ記号 |
これらは、MS-DOS時代からのルールである。ある意味、「command.com」のルールだとも言える。これらの文字がファイル名やフォルダー名に使えなくなったのは、コマンドラインで特別な意味を持つからである。MS-DOSはもともとコマンドラインですべての操作をする。このとき、コマンドラインで特別な意味を持つ記号文字に関しては、ファイルやフォルダー名での利用を禁止してコマンドラインやファイル名、フォルダー名の判定を簡略化した。
これらが今でも特殊扱いされていて、ファイルやフォルダーの名前に使えなくなっている。ただし、このことはNTFSやvFATなどのファイルシステムとしての仕様とは部分的にしか関係がない。パス区切り文字としての「\」と「/」は共通だが、他の文字は絶対ファイル名やパス名に入れられないのかというと、実はそうではない。ただし、ファイル名のAPIでもある程度の安全対策がしてあり、渡されたパスを解釈して処理している。そのため、APIやパラメーター指定によって、使えない文字には違いがある。なお、Windowsではどんな場合でも、「\\?\」で始まるパスは解釈処理をせず、そのまま扱う(ただしAPIが成功するとは限らない)。
コマンドラインでは「使えない」文字
現在のWindows 10でもコマンドラインからのコマンド利用は可能で、そのためにcmd.exeとpowershell.exeの2つのコマンドラインインタープリターがある。特にcmd.exeは、command.comの後継であり、多くの特性を引き継いでいる。しかし、長年の間にコマンドライン機能が強化されたことで、使い方に注意が必要な文字が生じている。その顕著な例が「スペース」だ。スペースはコマンドラインの引数を分離する記号文字としての働きがあり、MS-DOS時代はファイル名やパスにスペースを含めることができなかった。
現在も使われている「Program Files」というフォルダーは、vFATが導入されたWindows 95で登場した。「ファイル名にスペースが使えるんですよ」ということを簡単にユーザーに理解してもらうための命名だったのかもしれない。一方でそれにより、多くのユーザーはインストールされたアプリケーションの起動パスをダブルクオートで括らねばならなくなった。
cmd.exe内でダブルクオートで括らねばならない文字は、スペースだけではない。cmd.exeのオンラインヘルプによれば、ファイル名に以下の文字が含まれている場合には、ダブルクオートで括る必要がある。
& ( ) [ ] { } ^ = ; ! ' + , ` ~
これらは、コマンドラインやバッチでは特別な意味を持つ文字だ。たとえば、「&」は、cmd.exeでは、コマンドラインの区切りと解釈される。「^」は、cmd.exeのエスケープキャラクタとして使われている。基本的には、これらの文字がパスに含まれている場合、全体をダブルクオートで括れば安全である。このことはPowerShellでも同様だ。ただし、PowerShellでコマンドの引数ではなく、起動するプログラムのパスを表記するような場合に「&('パス')」という表記を使う必要がある。たとえば「c:\program files\test\test.exe」という実行ファイルの場合、cmd.exeでは
"c:\program files\test\test.exe"
とすればよいが、Powershellでは、
&'c:\program files\test\test.exe'
として先頭に「&」を置き、シングルクオートで括る必要がある。PowerShellではダブルクオートは変数展開をするため、変数を表す「$」がパス中に含まれていると、これが展開され変数値に置き換えられてしまう。シングルクオートはこれをしない(ちなみにcmd.exeはシングルクオートに特殊な意味を持たせずダブルクオートだけが有効)。
先頭に「&」は、後続部分を評価(実行)するという意味で、これがないと、PowerShellでは単なる文字列の表示コマンドになってしまう。このあたり、PowerShellが言語側にちょっと倒し過ぎちゃった感があり、シェルとしてはイマイチ人気がない理由の1つなのだと思う。プログラムのステートメントとしては、これでもいいのだが、コマンドラインの場合には、別処理にしてもいいんじゃないかと思う。ちなみに、スペースなどを含まずシングルクオートで括る必要がないパスには「&」を付ける必要はない。
入力行の補完機能を使えば、自動的に「&」を付けてシングルクオートで括ってくれる。しかし、それを使わずに手入力で「"C:\program files\……"」といったcmd.exe方式の実行ファイルの指定をすると、入力行が表示されるだけというのは、かなりダメージがあり、それ以来PowerShellが嫌いになったという多数のユーザーを作ってしまったのではないかと思われる。
cmd.exeは、簡易なパス入力が可能な反面、厄介な問題が結構ある。大きなものは「%」による環境変数の置換機能だ。cmd.exeのコマンドラインでは、環境変数名を「%」で囲った文字列は、実行前に環境変数の値に置換される。著名なのは、ユーザーのホームディレクトリを示す「%UserProfile%」だろう。
たとえば、「%UserProfile%\test.exe」とすれば、ユーザーのホームディレクトリにあるtest.exeコマンドを起動するコマンドになる。ところが、この環境変数置換は、環境変数が定義されてないと何も置き換えが起こらない。UserProfileは、Windowsが起動時に用意する環境変数なので、常に存在し置換されるが、testなどの環境変数名は定義されていないと置換されない。
このため「%test%.exe」といったコマンドラインは、testという環境変数がない場合には、文字通りのコマンドだが、testにxyzという文字列が定義されると、「xyz.exe」と置換されたのち起動しようとする。環境変数の置換を禁止するには「^」を使って「^%test^%.exe」と指定する必要がある。同様の文字には「!」があり、こちらは遅延環境変数置換が有効(cmd.exeの起動オプションなど)になっている場合、「%」とほぼ同じ意味を持つ(違いは、置換が行われるタイミング)。
なお、環境変数置換は、環境変数名の前後が%で囲まれている必要があり、片側のみの場合には置換されない。しかし、複雑なバッチファイル中で扱われた場合など、思わぬ副作用を生む可能性がある。そんなわけで、cmd.exeやpowershell.exeを使う場合には、使わない方がいい文字があるわけだ。
この連載の記事
-
第460回
PC
Windowsでsftpを使う -
第459回
PC
WSL 2.4.4ではtar形式でのディストリビューションが配布でき、企業での利用が容易になってきた -
第458回
PC
Windows上でhostsファイルを活用する -
第457回
PC
IPv6アドレスは先頭を見ればどんな種類かわかる -
第456回
PC
あらためてIPv6基本のキ -
第455回
PC
Windowsで現在どのネットワークアダプタがインターネット接続に使われているかを調べる方法 -
第454回
PC
Windows 11 24H2では「デバイスの暗号化」の条件が変わり、より多くのPCでドライブが暗号化される -
第453回
PC
Windows 11 24H2の配布開始後もすぐにはやってこない Windows UpdateとSafeguard Holds -
第452回
PC
Windows 11 Ver.24H2が登場 Copilot+ PCとそうでないPCで実質Windowsが2つに分かれる -
第451回
PC
新しいWindowsサンドボックスではコマンドラインからの制御が可能に -
第450回
PC
ユニコードで文字数を数える方法 - この連載の一覧へ