none
ショートファイル名の生成規則について RRS feed

  • 質問

  • いつもお世話になっております。

    いまいちカテゴリがわからなかったので間違っていたらご容赦ください。

    今まで気にしていなかったのですが、Windowsにはロングファイル名とショートファイル名があるようで、
    9文字以上のファイル名にした場合やスペースなどが入ったファイル名にした場合、自動的にショートファイル名が生成されるようなのですが、
    その生成規則を教えていただけないでしょうか。OSはWindows2000以降でお願いします。

    なぜかと言いますと、私はVBScriptならびにC#にてファイルをコピーするバッチを作成しております。

    その際、コピーするファイルとコピー先フォルダにある他のファイルとの名前は基本的に被らないようにしているのですが、
    コピー元ファイル名(8文字以下)とコピー先のフォルダにある他のファイルのショートファイル名が被ってしまうと上書きコピーされてしまうのではないかと
    懸念したからです。

    図で示しますと

    コピー元フォルダ                                   コピー先フォルダ
    [AAAAAA~1.txt]  ==コピー(上書き指定)==⇒ [AAAAAAAAAAAAAAAAABCDE.txt(ショートファイル名:AAAAAA~1.txt)]←たまたまコピー元と被ってしまった!!

    上図の場合はC#では上書きされることを確認しました。コピー元ファイル「AAAAAA~1.txt」は生成されたショートファイル名ではなくこういう名前です。

    ファイルの名前付け規則を作って回避しようにも、そもそものショートファイル名の命名の規則がわからないので困っている状態です。
    実際には、私はファイル名に「~(チルダ)」を使用することはないので、詳細な命名規則がわからなくとも、
    生成されるショートファイル名に必ずチルダが入ることが確認できれば上書きされる心配はないのですが、ご存知の方いらっしゃいますでしょうか。

    参考までに以下のようなサイトは発見しましたが、知りたいWindowsのバージョンまではわかりませんでした。

    http://support.microsoft.com/default.aspx/kb/142982/ja


    また別の回避策も教えていただけるとありがたいです。

    よろしくお願いします。
    2009年8月18日 10:19

すべての返信

  • VBSでFileSystemObjectのCopyFileなら3番目の引数をFalseにすれば、コピー先に同名のファイルがあるとエラーになります。
    C#でSystem.IO.File.Copyを使う場合でも3番目の引数をfalseにすれば、コピー先に同名のファイルがあるとIOExceptionが発生しますよ。

    こういったCopyではなく自分でファイルを開いてデータを書き込んでいくコピーでも、書き込みファイルが存在するとエラーになるようにSystem.IO.FileMode.CreateNewにしておけば問題ないと思いますが。

    #ショートファイル名の生成規則は知りません。
    2009年8月18日 10:49
  • gekkaさん

    すばやい回答ありがとうございます!

    コピー先にファイルがあるとエラーにする方法は知っているのですが、エラー時のリランを考えると上書きの方がありがたいのです。

    一般的には上書きしないようにプログラムを作るのかもしれませんが、これからプログラムを何年もしていく中で上書きをした方がよい場面も
    きっとあるのではないかと思っています。

    そういった場合にも参考として知っておきたいと思った次第です。

    2009年8月18日 11:01
  • System.IO.Path.GetFullPathと、APIのGetShortPathNameを駆使してチェックします?
    #エラー処理よりもチェックのコストのが大きくなりそうな気がします。

    チェックしたところで、チェックとコピー開始までの間に新たに重複するファイルが作成されていないという保証は無いので、必ずエラーチェックは必要になると思いますよ?
    2009年8月18日 11:28
  • >チェックしたところで、チェックとコピー開始までの間に新たに重複するファイルが作成されていないという保証は無いので、必ずエラーチェックは必要になると思いますよ?

    おっしゃるとおり、ショートファイル名のチェックをしても時間差があるので完璧ではないと思います。

    コピー先のフォルダには同じ(ロング)ファイル名のファイルは置かないという決めごとになっており、
    また、作ろうとしているバッチで作成されるファイルは、エラーによる再実行により何度上書きしても問題ないという作りにする予定です。

    ですので、全く別のファイルが上書きされることのみ懸念しております。

    結局のところ、上書きしないようにする(エラーするようにする)しかないのかもしれません。


    補足ですが、文字コードを変換するアプリケーション(たぶん市販のもの)を実行してみたところ、こちらも同様にショートファイル名のファイルを上書きするようなつくりになっていました。
    (わざと重複する名前で実行しました。)

    プログラムじゃなくてファイル名を指定する側が気をつけるべきなのでしょうか。

    すべてのファイル名を8文字以下あるいは9文字以上で統一すれば、確かに防げるっちゃ防げるんですが…。

    2009年8月18日 12:48
  • 手元の環境 (Windows 7) では現象を再現できなかったのですが、ファイルを上書く現象が発生した OS は何でしょうか?
    Windows 2000 ですと SP で同じような現象が修正されています。(XP でどうなるかは未確認です)

     ショート ファイル名とロング ファイル名の両方が使用されているコピー元からファイルをコピーするとファイルが失われることがある
     http://support.microsoft.com/kb/195144/ja

    この KB に該当する OS であれば、こちらの回避策に倣うのが自然に思えます。

    ちなみに、ショートファイル名には「~ (チルダ)」があると思い込んではいけないようで。

     The Old New Thing : Not all short filenames contain a tilde
     http://blogs.msdn.com/oldnewthing/archive/2004/04/14/113052.aspx
    2009年8月19日 3:16
  • totojoさん

    回答ありがとうございます。

    まず
    >ショート ファイル名とロング ファイル名の両方が使用されているコピー元からファイルをコピーするとファイルが失われることがある

    のところですが、

    [コピー元フォルダ]                         [コピー先フォルダ]
    ・LONGFILE.txt(LONGFI~1.txt)                ファイルがひとつもない。
    ・LONGFI~1.txt

    以上のような状態ですと、確かに不具合はでないようです。当方の環境はWindows Vistaです。

    しかし、

    [コピー元フォルダ]                         [コピー先フォルダ]
    ・LONGFI~1.txt                           ・LONGFILE.txt(LONGFI~1.txt)
                                          ・その他ファイル1
                                                                        ・その他ファイル2

    以上のようにコピー先フォルダにショートファイル名が同じものを設置しておき、
    C#で
    System.IO.File.Copy("コピー元フォルダ\LONGFI~1.txt", "コピー先フォルダ\LONGFI~1.txt", true);

    を実行しますと上書きされます。

    >ちなみに、ショートファイル名には「~ (チルダ)」があると思い込んではいけないようで。

    どうやらファイルシステムによってはチルダがつかないようですね。
    私は今のところWindowsしか使う予定はないので、
    FAT32かNTFSで、Windows2003、Windows2008のときのショートファイル名が分かればよいと思っています。

    探したらWindows2003については規則を発見致しました。
    http://technet.microsoft.com/en-us/library/cc781134(WS.10).aspx

    あとはWindows2008についてわかればいいなと思っています。
    もう少し探してみますが、無かったらなかったでまたコメントを書こうと思います。

    ありがとうございました。
    2009年8月19日 10:29
  • >探したらWindows2003については規則を発見致しました。
    >http://technet.microsoft.com/en-us/library/cc781134(WS.10).aspx
    >
    >あとはWindows2008についてわかればいいなと思っています。

    (少ないとは思いますが)規則は変わる可能性があるので、規則を利用してどうこうするというアイデアは、あまりよくないような気がします。

    スクリプトで出来るかどうか分かりませんが、コピー元のファイル名がロング名=ショート名の時、コピー先に同じショート名と異なるロング名を持つファイルがあるかどうか事前チェックして、その結果で処理を振り分けるくらいしか手はないような気がします。(事前チェック自体、それほど良い手だとは思いませんが)

    2009年8月20日 0:57
  • 渋木宏明さん

    回答ありがとうございました。

    返信遅くなり申し訳ありませんでした。

    言われるとおり規則は変わるかもしれませんね。

    ひとまずフォルダに入るファイルは決まっているので、今回は上書きされる可能性のあるファイルだけチェックすることにします。

    次の修正時にちゃんとファイル名等を考えたいと思います。

    Windows2008については結局見つからなかったので、回答済みにするのはもう少し待とうと思います。
    2009年8月31日 13:02