質問: バッチファイルで、サブディレクトリの2階層以下にあるファイルを 1階層直下に移動させるというバッチのコードを作成しました。 ``` SETLOCAL enabledelayedexpansion cd C:\Users\Desktop\Test for /d %%i in (*) do ( cd %%i for /r . %%j in (*) do ( move "%%j" ) cd .. ) ``` 上記の記述の環境ではTestディレクトリ配下に数100のサブディレクトリ(A,B,Cとする)が あり、それぞれのサブディレクトリ中にも複数のサブディレクトリ(D,E,Fとする)が あります。 実行例は以下です。 ========例======== ◎実行前 C:\Users\Desktop\Test | |----A---D---1234.txt | |----B---E---5678.xls | |----C---F---9012.pdf ◎実行後 C:\Users\Desktop\Test | |----A---1234.txt---D | |----B---5678.xls---E | |----C---9012.pdf---F D、E、FにあったファイルをA、B、C直下に移動させることは出来たのですが、 この場合実行前からAフォルダに1234.txtがある場合上書きを確認されます。 ●回答希望事項 上書きはさせたくなく、可能なら同名ファイルはある分リネーム「_1とか(1)」をするように 動作させたいと考えております。 良い記述がみつからず困っております。 どうかお知恵をおかしください。 よろしくお願い致します。
回答: `move "%%j"` 第2引数に「..」を書いているんですよね? とりあえず、<どこかフォルダー>にあるファイルを親フォルダーに移動する汚いサンプルコードを置いておきます。対象のパス名にスペースなどが入っている場合や、その他エラーの考慮は一切していません。 提示されたコードの%%iのループに相当する部分はあえて書いていません。 ``` @echo off setlocal enabledelayedexpansion rem カレントフォルダーを移動前のファイルがある<どこかのフォルダー>へ変更 pushd <どこかのフォルダー> rem ファイル毎のループ for /r . %%j in (*) do ( rem リネーム移動のサブルーチン呼び出し call :renmove %%j .. ) rem カレントフォルダーを実行前の場所に戻す popd rem これより後ろはサブルーチンなのでバッチ処理を終了 exit /b rem ファイルを移動するサブルーチン rem 引数:<移動元のファイル> <移動先フォルダー> :renmove rem 連番の初期値 set num=0 rem 移動先のファイルパス set distfile=%2\%~nx1 rem 移動可能なファイル名が見つかるまでループ :renmove_loop rem 移動先に同名のファイルがあるか if exist !distfile! ( rem 連番を更新(初回は0+1)して、移動先のファイルパスを再構成 set /a num=num + 1 set distfile=%2\%~n1_!num!%~x1 rem 再判定のためループ goto :renmove_loop ) rem moveコマンドは移動先のファイル名を指定すればリネームできる move %1 !distfile! exit /b ``` p.s. サラ書きのはずが、forループ中のgotoの罠の存在を忘れていて悩んでしまった...。