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

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

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

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

Q&A

解決済

2回答

3618閲覧

C#でサブフォルダー内のサブフォルダーのような順番で全てのサブフォルダーの絶対パスを一括取得する方法

PIYOPIYO_16

総合スコア1

C#

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

0グッド

0クリップ

投稿2020/08/21 13:01

知りたいこと

フォルダー ┣ サブフォルダー1 ┃ ┗サブフォルダー1_1 ┃ ┗サブフォルダー1_1_1 ┃ ┗ サブフォルダー2 ┗サブフォルダー2_1

C#でWindowsアプリケーションを作っています。
上記のような、フォルダー階層を持つフォルダーのすべてのサブフォルダーの絶対パスをリストとして一括で取得したいと考えています。
その際に、以下のようにサブフォルダー内のサブフォルダーが先にくるような順番になるように取得する方法がございましたら、ご教授いただけないでしょうか?
0.  フォルダー/サブフォルダー1
0. フォルダー/サブフォルダー1/サブフォルダー1_1
0. フォルダー/サブフォルダー1/サブフォルダー1_1/サブフォルダー1_1_1
0. フォルダー/サブフォルダー2
0. フォルダー/サブフォルダー2/サブフォルダー2_2

試したこと

C#

1using System; 2using System.Collections.Generic; 3 4namespace sample 5{ 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 //"C:\フォルダー"以下のサブフォルダをすべて取得する 11 IEnumerable<string> subFolders = System.IO.Directory.EnumerateDirectories(@"C:\フォルダー", "*", System.IO.SearchOption.AllDirectories); 12 13 //サブフォルダを列挙する 14 foreach (string subFolder in subFolders) 15 { 16 Console.WriteLine(subFolder); 17 } 18 } 19 } 20}

上記のコードですべてのサブフォルダーの絶対パスを取得することはできましたが、取得した順番が以下のようになっており、取得したい順番で取得できませんでした。
並び変えることで問題は解決すると思ったのですが、正確かつ高速なソート方法が思いつかず困っています。
0.  フォルダー/サブフォルダー1
0. フォルダー/サブフォルダー2
0. フォルダー/サブフォルダー1/サブフォルダー1_1
0. フォルダー/サブフォルダー2/サブフォルダー2_2
0. フォルダー/サブフォルダー1/サブフォルダー1_1/サブフォルダー1_1_1

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

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

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

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

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

YAmaGNZ

2020/08/21 14:10

回答しておいてですが SubFolder1、SubFolder2、SubFolder11の並び順は SubFolder1 SubFolder2 SubFolder11 ですか? SubFolder1 SubFolder11 SubFolder2 ですか?
guest

回答2

0

ベストアンサー

EnumerateDirectoriesでサブフォルダまで全て列挙するのではなく、直下のフォルダのみ列挙する関数を再帰呼び出しするのはどうでしょう?

追記

自然順のソートなのであれば

C#

1IEnumerable<string> subFolders = System.IO.Directory.EnumerateDirectories(@"C:\フォルダー", "*", System.IO.SearchOption.AllDirectories); 2subFolders = subFolders.OrderBy(f => f, new NaturalStringComparer()); 3 4 5public class NaturalStringComparer : IComparer<string> 6{ 7 [System.Runtime.InteropServices.DllImport("shlwapi.dll", CharSet = System.Runtime.InteropServices.CharSet.Unicode, ExactSpelling = true)] 8 private static extern int StrCmpLogicalW(string x, string y); 9 10 public int Compare(string x, string y) 11 { 12 return StrCmpLogicalW(x, y); 13 } 14 15} 16

といった感じでStrCmpLogicalWを利用してのソートですかね

さらに追記

シンボリックリンクを回避するとなると

C#

1public void GetSubfolders(string folderName, ref List<string> subFolders) 2{ 3 //folderNameにあるサブフォルダを取得 4 foreach (string folder in GetDirectories(folderName)) 5 { 6 // シンボリックリンクの場合は属性がFileAttributes.ReparsePointとなるので除外 7 // もし、列挙するがその下の検索はしないのであれば、Listに追加のみとし、再帰で呼ばないようにする 8 if (!File.GetAttributes(folder).HasFlag(FileAttributes.ReparsePoint)) 9 { 10 //リストに追加 11 subFolders.Add(folder); 12 //再帰的にサブフォルダを取得する 13 GetSubfolders(folder, ref subFolders); 14 } 15 16 } 17} 18

このように直下のフォルダのみを列挙し、1つづつ属性をチェックしながら再帰呼び出しを行うのがいいのではないでしょうか

投稿2020/08/21 13:16

編集2020/08/21 15:46
YAmaGNZ

総合スコア10240

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

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

PIYOPIYO_16

2020/08/21 14:57

ご回答ありがとうございます。 ソート自体は`StrCmpLogicalW`でできそうでした。 追加でお聞きしたいのですが、サブフォルダー1_1に親フォルダー(サブフォルダー1)へのシンボリックリンクがある場合、`EnumerateDirectories`で無限ループになることが考えられるのですが、回避するためには、ご提案いただいた「直下のフォルダのみ列挙する関数を再帰呼び出しする」方法を用いるのが良いでしょうか?
PIYOPIYO_16

2020/08/23 15:12

追加の質問にも回答いただきありがとうございます。 教えていただいたコードを参考に、再帰呼び出しで取得するようにしたいと思います。
guest

0

LINQのOrderByを使えばソートできます。

C#

1using System; 2using System.Linq; 3using System.Collections.Generic; 4・・・ 5//"C:\フォルダー"以下のサブフォルダをすべて取得する 6IEnumerable<string> subFolders = System.IO.Directory.EnumerateDirectories(@".\フォルダー", "*", System.IO.SearchOption.AllDirectories); 7 8subFolders = subFolders.OrderBy(s => s); 9//サブフォルダを列挙する 10foreach (string subFolder in subFolders) 11{ 12 Console.WriteLine(subFolder); 13}

投稿2020/08/21 14:01

yureighost

総合スコア2183

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

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

PIYOPIYO_16

2020/08/21 14:56

回答ありがとうございました。 教えていただいた方法でソートできました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問