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

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

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

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

Q&A

解決済

1回答

759閲覧

C# フォルダ名を一斉に書き換える処理でフォルダパスをどうやって編集したらいいのか知りたい。

退会済みユーザー

退会済みユーザー

総合スコア0

C#

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

0グッド

0クリップ

投稿2022/07/24 02:26

提示コードですが////コメント部で囲ってる内部のコードで以下のErrorが発生します。原因は先にうえのディレクトリ名を変えているためその後のディレクトリパスも変更をする必要があるにも関わらず変更していないことが原因による例外なのですがこれはどう対処すればいいのでしょうか?対象方法が知りたいです。

フォルダ階層
C:\Users\yw325\Desktop\test\aaaルダー - コピー C:\Users\yw325\Desktop\test\aaaルダー - コピー\12345 - コピー C:\Users\yw325\Desktop\test\aaaルダー - コピー\12345 - コピー (10) C:\Users\yw325\Desktop\test\aaaルダー - コピー\12345 - コピー (11) C:\Users\yw325\Desktop\test\aaaルダー - コピー\12345 - コピー (12) C:\Users\yw325\Desktop\test\aaaルダー - コピー\12345 - コピー (2) C:\Users\yw325\Desktop\test\aaaルダー - コピー\12345 - コピー (3) C:\Users\yw325\Desktop\test\aaaルダー - コピー\12345 - コピー (4) C:\Users\yw325\Desktop\test\aaaルダー - コピー\12345 - コピー (5) C:\Users\yw325\Desktop\test\aaaルダー - コピー\12345 - コピー (6) C:\Users\yw325\Desktop\test\aaaルダー - コピー\12345 - コピー (7) C:\Users\yw325\Desktop\test\aaaルダー - コピー\12345 - コピー (8) C:\Users\yw325\Desktop\test\aaaルダー - コピー\12345 - コピー (9)

#####エラー

System.IO.DirectoryNotFoundException: 'Could not find a part of the path 'C:\Users\yw325\Desktop\test\aaaaaaaaルダー - コピー

cs

1using System; 2using System.IO; 3 4public class Program 5{ 6 /*################################################ 7 * 8 * 9 * 10 * 11 * 12 #################################################*/ 13 14 static List<string> dirList = new List<string>(); //ディレクトリパスリスト 15 16 public static void GetSubFolderPathList(string startPath) 17 { 18 foreach(string path in Directory.GetDirectories(startPath)) 19 { 20 if(System.IO.Directory.Exists(path) == true) 21 { 22 dirList.Add(path); 23 Console.WriteLine(path); 24 //Console.WriteLine(System.IO.Directory.GetParent(path).Name); 25// Console.WriteLine(System.IO.Path.GetFileName(path)); 26 27 // Console.WriteLine(System.IO.Path.Combine(System.IO.Directory.GetParent(path).Name,System.IO.Path.GetFileName(path))); 28 29 30 GetSubFolderPathList(path); 31 32 } 33 } 34 } 35 36 37 public static void ReWriteFolder(int position,int num) 38 { 39 40 } 41 42 43 public static int GetMostMinFolderName() 44 { 45 List<int> list = new List<int>(); 46 foreach(string path in dirList) 47 { 48 list.Add(System.IO.Path.GetFileName(path).Length); 49 } 50 51 list.Sort(); 52 53 54 return list[0]; 55 56 57 58 } 59 60 public static void Main() 61 { 62 while(true) 63 { 64 string? folderPath = null; 65 Console.Write("input rename folder path: "); 66 67 folderPath = Console.ReadLine().Trim('\"'); //フォルダーをD&D 68 69 Console.WriteLine(""); 70 71 Console.WriteLine("rewirte subfolder\n"); 72 73 GetSubFolderPathList(folderPath); //再帰的にサブフォルダーを取得 74 Console.WriteLine(""); 75 76 if (dirList.Count != 0) 77 { 78 //dirList.Add(folderPath); //ルートフォルダのパスを格納 79 80 string n; 81 bool isStart = false; 82 do 83 { 84 Console.Write("number to delete: "); 85 86 n = Console.ReadLine(); 87 88 if(n.All(char.IsDigit) == true) 89 { 90 int number = int.Parse(n); 91 92 // 書き換え結果を確認 93 foreach (string path in dirList) 94 { 95 //string parent = System.IO.Directory.GetParent(path).Name; 96 97 try 98 { 99 Console.WriteLine(System.IO.Path.GetFileName(path).Remove(0,number)); 100 } 101 catch(System.ArgumentOutOfRangeException e) 102 { 103 //指定した文字位置がフォルダ名より長いとき 104 n = (GetMostMinFolderName() - 1 ).ToString(); 105 106 Console.WriteLine(System.IO.Path.GetFileName(path).Remove(0, GetMostMinFolderName() - 1)); 107 108 } 109 110 111 //Console.WriteLine(System.IO.Path.Combine(System.IO.Directory.GetParent(path).Name, System.IO.Path.GetFileName(path))); 112 113 } 114 115 // 書き換えを実行するか確認 116 string yn; 117 do 118 { 119 Console.Write("start rewrite? [y/N]: "); 120 yn = Console.ReadLine(); 121 122 if(yn == "y") 123 { 124 isStart = true; 125 } 126 else if(yn == "N") 127 { 128 isStart = false; 129 } 130 131 } 132 while( (yn != "N") && (yn != "y") ); 133 134 } 135 136 } 137 while( (n.All(char.IsDigit) == false) || (isStart == false) ); 138 139 int num = int.Parse(n); //削除文字位置 140 141 foreach(string path in dirList) 142 { 143 // string parent = System.IO.Directory.GetParent(path).Name; 144 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 145 Console.WriteLine(System.IO.Directory.GetParent(path).ToString()); 146 string newPath = System.IO.Path.Combine(System.IO.Directory.GetParent(path).ToString(), System.IO.Path.GetFileName(path).Remove(0, num)); 147 System.IO.Directory.Move(path,newPath); 148 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 149 150 } 151 152 153 154 155 } 156 else 157 { 158 Console.WriteLine("no subfolder process cancel\n\n"); 159 } 160 161 162 dirList.Clear(); //サブフォルダーパスを初期化 163 } 164 165 166 167 168 // System.IO.Directory.Move("12345","123"); 169 170 Console.ReadLine(); 171 } 172 173}

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

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

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

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

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

y_waiwai

2022/07/24 04:23

何をやりたいんでしょうか また、どういう問題が出ていて、それをどうしたいというはなしなんでしょう
KOZ6.0

2022/07/24 10:55

親を先に移動するから問題なので、子から処理すればよいと思います。 dirList を逆順にソートして処理すれば問題ないかと。
guest

回答1

0

ベストアンサー

要するに、親フォルダをリネームした結果、サブフォルダのフルパスが変わってしまい、最初に取得しておいたフォルダのリストとパスが一致しなくなったのが問題なんでしょう。

対応方法としては、フォルダリネーム時に取得しておいたフォルダリストのパスも書き変えるか、サブフォルダを取得しなおすしかありません。


以下は遅延評価を利用してサブフォルダの再帰探索中に処理するように全面的に書き変えたサンプルです。
VS2022 + .NET6(C#10) 環境で動作確認しています。C#の新しめの機能を積極的に使っているので古い環境ではビルドできないかも。その場合は、適宜読み替えてください。
※コードから仕様を読み取っているので仕様を間違っているかもしれません。

C#

1while( true ) { 2 // 処理するルートフォルダパスを標準入力から取得 3 // ※ 入力されるまで無限ループ 4 Console.Write( "input rename folder path: " ); 5 string rootPath; 6 while( true ) { 7 var s = Console.ReadLine()?.Trim(); 8 if( s != null ) { 9 rootPath = s; 10 break; 11 } 12 } 13 14 // フォルダ名から取り除く文字数を標準入力から取得 15 // ※ 数値が入力されるまで無限ループ 16 int number; 17 while( true ) { 18 Console.Write( "number to delete: " ); 19 if( int.TryParse( Console.ReadLine()?.Trim(), out number ) ) 20 break; 21 } 22 23 /// <summary> 24 // 指定したフォルダのサブフォルダを再帰的に列挙する関数。遅延評価。 25 // 親フォルダ → サブフォルダ の順番で列挙する 26 /// </summary> 27 /// <param name="parent">サブフォルダを列挙するルートフォルダ</param> 28 /// <returns>サブフォルダの列挙子</returns> 29 static IEnumerable<DirectoryInfo> GetDirectories( DirectoryInfo parent ) { 30 foreach( var d in parent.GetDirectories() ) { 31 yield return d; 32 33 foreach( var d2 in GetDirectories( d ) ) { 34 yield return d2; 35 } 36 } 37 } 38 39 // サブフォルダの一覧を取得 ※ 遅延評価 40 var directories = GetDirectories( new DirectoryInfo( rootPath ) ); 41 42 // サブフォルダが無ければ最初からやり直し 43 if( !directories.Any() ) { 44 Console.WriteLine( "no subfolder process cancel\n\n" ); 45 continue; 46 } 47 48 // (フォルダ名から取り除く文字数) が (サブフォルダ名の文字数) 以上の場合は、 49 // (サブフォルダ名の文字数) - 1 に調整 50 // ※ フォルダ名が1文字のフォルダ存在した場合、number が 0 になってしまうが、 51 //   本当に意図した仕様? 52 number = Math.Min( number, directories.Min( d => d.Name.Length ) - 1 ); 53 54 // サブフォルダの一覧を取得 ※ 遅延評価 55 // ※ 前の処理で列挙済みのため再度取得 56 directories = GetDirectories( new DirectoryInfo( rootPath ) ); 57 58 // サブフォルダのフォルダ名の先頭 number 文字を削除 59 // ※ 遅延評価の為、サブフォルダ評価時に親フォルダの変更は反映済み 60 foreach( var d in directories ) { 61 if( d.Parent == null ) continue; 62 var newName = Path.Combine( d.Parent.FullName, d.Name[number..] ); 63 d.MoveTo( newName ); 64 } 65} 66 67// 元コードにあったので入れたが、while で無限ループしているのでここには到達しない 68Console.ReadLine();

投稿2022/07/24 08:10

draq

総合スコア2573

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

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

退会済みユーザー

退会済みユーザー

2022/07/24 12:22

なるほど。list.Reverse();を使って文字列の長い順にしましたがディレクトリー階層の深さとは無関係なので無意味ですよね。そのやり方でやってみます。
KOZ6.0

2022/07/24 14:47

Reverse は単純に順番を入れ替えるだけです。 簡単にやるなら Sort して Reverse でしょう。 逆順にソートした場合、あるフォルダの親フォルダがリスト内にあれば、かならずその位置より後に来ます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問