質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

4回答

20601閲覧

System.IO.Directory.GetFiles の挙動について

Nakashige

総合スコア15

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

3グッド

3クリップ

投稿2017/01/26 11:19

編集2017/01/26 15:03

【開発環境】
Windoes10(x64)
Visual Studio 2013

現在、任意のフォルダーに対してファイル一覧を取得する関数を作成しています。
ここで問題が発生しました。

以下のようなファイル構成と仮定します。

■Cドライブ
c:\tmp\sample.xls
c:\tmp\sample.xlsx

■Dドライブ
d:\tmp\sample.xls
d:\tmp\sample.xlsx

ここで、下記コードを実行すると、取得できるファイルが異なります。

C#;

1string path1 = @"c:\tmp"; 2Directory.GetFiles(path1, "*.xls"); // sample.xls, sample.xlsx どちらも取得できる 3 4string path2 = @"d:\tmp"; 5Directory.GetFiles(path2, "*.xls"); // sample.xls のみ取得できる

Directory.GetFiles メソッド
MSDN を参照すると、必ず xls, xlsx どちらのファイルも取得できると考えています。

以下、MSDN(Directory.GetFiles)のメモを引用

アスタリスクのワイルドカード文字を使用する場合、 searchPattern 「.txt」など、指定した拡張子の文字数影響を与えます検索次ようにします。
指定された拡張機能が 3 文字の場合は、指定した拡張子が始まる拡張子を持つファイルを返します。
たとえば、「
.xls」には、"book.xls"と"book.xlsx"両方が返されます。
その他のすべてのケースでは、メソッドは、指定された拡張機能を正確に一致するファイルを返します。
たとえば、"* .ai"が"file.ai"、"file.aif"を返します。
疑問符 () のワイルドカード文字を使用すると、このメソッドは、指定されたファイル拡張子に一致するファイルのみを返します。
たとえば、ディレクトリの検索パターンに 2 つのファイル、"file1.txt"および"file1.txtother"指定された"ファイル? です。txt"は最初のファイルだけを返し、"file*.txt"の検索パターンには、両方のファイルが返されます。

なぜDドライブ内のフォルダーに対しては xlsx が取得できないのでしょうか?

ご存じの方がいらっしゃいましたら、ご回答いただけますようお願いいたします。

【追記】
検証情報をいただいたため、追記します。

・Windows7環境では現象が発生しません
・ドライブはいずれもNTFSです
・Windows10、及びWindowsServer2016で現象を確認しています。

以上

matobaa, good_island, KSwordOfHaste👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

どうやら、"8.3形式のファイル名を生成するか否か"の設定が影響するようですね。

昔のOSではファイル名はドットの前が8文字まで、ドットの後が3文字まで、という制限がありました。
これを"8.3形式"と呼んだりします。
その名残で、今のWindowsでも内部的に8.3形式の名前を持つことがあり、
dirコマンドに/xオプションをつけると8.3形式の名前が確認できます。

bat

1C:\tmp>dir /x 2 ドライブ C のボリューム ラベルがありません。 3 ボリューム シリアル番号は 857D-9700 です 4 5 C:\tmp のディレクトリ 6 72017/01/27 13:41 <DIR> . 82017/01/27 13:41 <DIR> .. 92017/01/27 13:02 22,528 sample.xls 102017/01/27 13:01 6,265 SAMPLE~1.XLS sample.xlsx 11 2 個のファイル 28,793 バイト 12 2 個のディレクトリ 683,712,335,872 バイトの空き領域 13 14C:\tmp>d: 15 16D:\>cd tmp 17 18D:\tmp>dir /x 19 ドライブ D のボリューム ラベルは vhd です 20 ボリューム シリアル番号は F4D3-1360 です 21 22 D:\tmp のディレクトリ 23 242017/01/27 13:28 <DIR> . 252017/01/27 13:28 <DIR> .. 262017/01/27 13:02 22,528 sample.xls 272017/01/27 13:01 6,265 sample.xlsx 28 2 個のファイル 28,793 バイト 29 2 個のディレクトリ 1,045,876,736 バイトの空き領域

8.3形式のファイル名を生成するか否かは、ボリュームごとに設定することができます(Windows 7以降)。
たとえば私の環境の場合、Cは有効、VHDでNTFSにしたDは無効でした。

bat

1C:\WINDOWS\system32>fsutil behavior query disable8dot3 c: 2ボリュームの状態は 0 です (8dot3 名の作成は有効です)。 3レジストリの状態は 2 です (ボリューム単位で設定します - 既定値)。 4 5上の 2 つの設定に基づいて、8dot3 名の作成は c: で有効です 6 7C:\WINDOWS\system32>fsutil behavior query disable8dot3 d: 8ボリュームの状態は 1 です (8dot3 名の作成は無効です)。 9レジストリの状態は 2 です (ボリューム単位で設定します - 既定値)。 10 11上の 2 つの設定に基づいて、8dot3 名の作成は d: で無効です

System.IO.Directory.GetFilesメソッドは、この8.3形式の名前も検索対象に含むようです。
そのため、8.3形式が有効なCでは2ファイルが取得され、
8.3形式が無効なDでは1ファイルのみ取得された、
ということのようです。

以上、まとめますと、

  • 8.3形式が有効なボリュームかどうかによってSystem.IO.Directory.GetFilesメソッドの挙動は異なる
  • 8.3形式が有効かどうかはfsutil behavior query disable8dot3で確認できる

ということになります。

参考:
8.3形式の短いファイル名を生成しないようにする - @IT

投稿2017/01/27 04:50

alg

総合スコア2019

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Nakashige

2017/01/27 09:24

ありがとうございます! 解決しました!!
hikochang

2017/01/27 11:26

"8.3形式のファイル名を生成するか否かは、ボリュームごとに設定することができます(Windows 7以降)。 " なんて、全く初耳でした! ファイルシステムまでは疑えたのですが、上記の様な設定が有るとは全く想像できませんでした。 8.3なども検索していたのですが見つけられませんでした。超参考になりました。
Nakashige

2017/01/27 12:46

本当にありがとうございました。 hikochang さんの「FAT32とNTFSで動きが違う」も勉強になりましたが、8.3形式もとても勉強になりました。 社内でも共有しておきます!!
guest

0

試してませんがFAT32とNTFSとで動作が違ったかも知れません。Dドライブは外付けのメモリか何かですよね?一度NTFSで確認して見ては?

投稿2017/01/26 14:44

hikochang

総合スコア648

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Nakashige

2017/01/26 14:52

回答ありがとうございます。 こちらの検証PCはすべてNTFSでした。 逆にFAT32環境では検証できておりません。 補足ですが ・Cドライブ、Dドライブが物理的に別れている場合 ・Cドライブをパーティションで区切ってDドライブを作成した場合 Windows10の場合では、上記のどちらでも現象が発生しております。
hikochang

2017/01/26 15:01

Dドライブがダメということですか? Eドライブにした場合は? 拡張子 *.AAA と*.AAAA でも発生しますか? Directory.GetFilesはFAT32とNTFSで動きが違うので、当たりかと思ってましたが、、、残念です
Nakashige

2017/01/26 15:25

Eドライブでも現象が発生していました。。 Cドライブだけが正常に動作しているようです。 >*.AAA, *.AAAA 検証してみましたが、現象が発生していました。 FAT32、NTFSで動作が異なることは知らなかったです。 勉強になりました、ありがとうございます m(_ _)m
hikochang

2017/01/26 15:40

*.* などを指定して全てを列挙した場合はどうでしょうか?
Nakashige

2017/01/26 15:56

すみません、今日はもう試せる環境ではないため、また明日改めて検証させていただきます。 お付き合いいただきありがとうございます。
Nakashige

2017/01/26 23:56

*.* の指定ではすべてのファイルが正常に列挙されます。 MSDNにもあるように、ワイルドカード+3文字拡張子の指定時の特別な挙動と認識しています。 ただ、今回私が作成したいプログラムは「*.xls」「*.xlsx」を列挙するプログラムです。 対象フォルダーによって動作が異なるので、実装者がそれを飲み込んだ上で実装しなければならないのかな、と疑問に思い投稿しました。
Nakashige

2017/01/27 09:58

いろいろとアドバイスいただきありがとうございます。 無事解決することができました。
guest

0

Windows 10 Enterprise 64bit Version 1607 OS Build 14303.693
Cドライブ:NTFSの内蔵HDD
Dドライブ:FAT32のUSBメモリ
.NET Framework 4.6

で試しましたが、CもDも2つのファイルが取得されました。
Ragさんとほぼ同じソースで、出力結果も一緒です。

しかし。
Dを容量固定のVHDでNTFSフォーマットして試してみたところ、
Nakashigeさんと同様にDはsample.xlsしか取得されませんでした。

OSとドライブのフォーマット の組み合わせが影響するのかもしれません。
あとはシステムドライブかそうでないか、
リムーバブルかどうか、
など色々考えられますね。

投稿2017/01/27 04:25

alg

総合スコア2019

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

回答にはなっていませんが失礼します。

同じ環境が準備できなかった為、
・Windows7 64bit
・.Net v4.0.30319(64bit と 32bit 両方でコンパイル)
の環境にて同等のソースを書いて実行してみたところ、意図したとおりの結果となりました。

私もこのメソッドを利用したツールをいくつか作って使っている為、環境で挙動が変化するとしたら心配です。
実行したソースと結果を張り付けておきます。

ソース

c#

1using System; 2using System.IO; 3 4class MainApp 5{ 6 public static void Main() 7 { 8 ShowDirectorys(); 9 } 10 11 private static void ShowDirectorys() 12 { 13 string path1 = @"c:\tmp"; 14 Show(path1, Directory.GetFiles(path1, "*.xls")); // sample.xls, sample.xlsx どちらも取得できる 15 16 string path2 = @"d:\tmp"; 17 Show(path2, Directory.GetFiles(path2, "*.xls")); // sample.xls のみ取得できる 18 } 19 20 private static void Show(string title, string[] texts) 21 { 22 Console.WriteLine( "===== " + title + " ====="); 23 foreach(var text in texts) 24 { 25 Console.WriteLine(text); 26 } 27 Console.WriteLine("=========="); 28 } 29}

結果

===== c:\tmp ===== c:\tmp\sample.xls c:\tmp\sample.xlsx ========== ===== d:\tmp ===== d:\tmp\sample.xls d:\tmp\sample.xlsx ==========

以上、失礼しました。

投稿2017/01/26 14:29

Rag

総合スコア19

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Nakashige

2017/01/26 14:43

検証ありがとうございます。 私も Windows7(x64) を用意して試してみたところ、正常に動作しました。 現状は、Windows10、及び WindowsServer2016 で問題の発生を確認しています。 OS依存なのかもしれません。。
Nakashige

2017/01/27 09:58

検証いただきありがとうございます。 無事解決することができました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問