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

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

新規登録して質問してみよう
ただいま回答率
85.31%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

バッチファイル

バッチファイル(Batch File)は、Windowsのコマンドラインインタープリターによって複数のコマンドを実行させる事が出来るスクリプトファイルです。

Q&A

解決済

1回答

581閲覧

バッチファイルで特定のフォルダに存在する複数の同一名称ファイルを別の一つのフォルダにまとめたいです。

T_Sajispoon_T

総合スコア1

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

バッチファイル

バッチファイル(Batch File)は、Windowsのコマンドラインインタープリターによって複数のコマンドを実行させる事が出来るスクリプトファイルです。

0グッド

0クリップ

投稿2023/08/10 02:09

編集2023/08/14 11:09

実現したいこと

各フォルダに存在する複数のcsvファイルを一つのフォルダにまとめたいです

前提

つい先日初めてバッチファイルを触り始めました。
特定のフォルダをbatファイルで実行して複数のcsvファイルを一つのフォルダにまとめたいと思っています。
しかしフォルダ内に存在する全てのcsvファイルは同一名称(ここではdatalist01.csv)になっていて一つのフォルダにまとめようとすると上書きされてしまうため、csvファイルの名前を変更(csvファイルが格納されている子フォルダ名(ここではtest_listA~...2023~...)を各csvファイル名の前半部分に足す)して一つのフォルダにまとめようとしています。

batファイル内で行いたい処理を示しますと以下のようになります。
・カレントフォルダに「test_all」フォルダを生成する
・実行したフォルダが空だった場合終了、それ以外なら次の処理へ
・実行フォルダ内の全てのcsvファイルに対して処理を実行
・各csvファイル名の前半部に各csvファイルが格納されているフォルダ名を付与してコピー
・コピー元は各csvファイルが格納されている各フォルダ、コピー先はtest_allフォルダ
・処理の終了

フォルダ構成を示しますと以下のようにしたいと思っています。

BAT_TEST/(BatファイルおよびCSVファイル群が格納されているフォルダ)
├─bat_test/(Batファイルで処理を行いたいフォルダ)
│  ├─test_listA/
│  │  ├─ test_listA202308/
│  │  │  └─ datalist01.csv
│  │  ├─ test_listA202309/
│  │  │  └─ datalist01.csv
│  │  ├─ test_listA202310/
│  │  │  └─ datalist01.csv
│  │  └─ ...
│  │
│  ├─ test_listB/
│  │  ├─ test_listB202308/
│  │  │  └─ datalist01.csv
│  │  ├─ test_listB202309/
│  │  │  └─ datalist01.csv
│  │  ├─ test_listB202310/
│  │  │  └─ datalist01.csv
│  │  └─ ...
│  └─ ...
└─ test.bat

batファイルで処理後

BAT_TEST/(BatファイルおよびCSVファイル群が格納されているフォルダ)
├─bat_test/(Batファイルで処理を行いたいフォルダ)
│  ├─test_listA/
│  │  ├─ test_listA202308/
│  │  │  └─ datalist01.csv
│  │  ├─ test_listA202309/
│  │  │  └─ datalist01.csv
│  │  ├─ test_listA202310/
│  │  │  └─ datalist01.csv
│  │  └─ ...
│  │
│  ├─ test_listB/
│  │  ├─ test_listB202308/
│  │  │  └─ datalist01.csv
│  │  ├─ test_listB202309/
│  │  │  └─ datalist01.csv
│  │  ├─ test_listB202310/
│  │  │  └─ datalist01.csv
│  │  └─ ...
│  └─ ...

├─test_all(Batファイル実行後作成されるフォルダ、および処理したCSVファイルを格納するフォルダ)
│  ├─test_listA/
│  │  ├─ test_listA202308datalist01.csv(名称を変更したtest_listA202308に格納されていたCSVファイル)
│  │  ├─ test_listA202309datalist01.csv(名称を変更したtest_listA202309に格納されていたCSVファイル)
│  │  ├─ test_listA202310datalist01.csv(名称を変更したtest_listA202310に格納されていたCSVファイル)
│  │  └─ ...
│  │
│  ├─ test_listB/
│  │  ├─ test_listB202308datalist01.csv(名称を変更したtest_listB202308に格納されていたCSVファイル)
│  │  ├─ test_listB202309datalist01.csv(名称を変更したtest_listB202309に格納されていたCSVファイル)
│  │  ├─ test_listB202310datalist01.csv(名称を変更したtest_listB202310に格納されていたCSVファイル)
│  │  └─ ...
│  └─ ...

└─ test.bat

発生している問題・エラーメッセージ

(※バッチファイルのエラーメッセージをどう出力すればいいのかわかりませんでした...)

・test_allフォルダは生成されるがそれ以降の処理が正常に動作していない、しかし原因がわからない。
・test_allフォルダ内にもcsvファイルが格納されている各フォルダを生成できていない
(上記構成だとtest_all\test_listA,B...←csvがコピーされてきた格納されるこのフォルダ群)
・コピー元やコピー先のパス指定の仕方が理解できておらず、どう記述すればいいかわからない
(copy コピー元 コピー先 名前 とするとみたがパスでの指定がわからない)
・ファイル名の変更がうまくいかない、わからない

=========以下8/14追記===========================

簡易的に作成したフォルダ構成にてバッチファイルを実行するフォルダを指定して処理を行った結果(追記上部コード)正常に動作したが
バッチファイルに対して様々なファイルをドラッグ&ドロップで処理を実行したいため、追記下部コードにてset "TargetFolder=%~dp1"でバッチファイルを実行したフォルダのパスを指定してみたが、12行目までしか正常に動作しませんでした。
19行目、24行目のfor /d %%j in ("%TargetFolder%%%i*")が間違っているのだと思いますが、解決策がわからずじまいになっています。
大変申し訳ないのですが現状の限界を感じております。助力のほどいただけたら幸いです。

該当のソースコード

bat

1@echo off 2 3:rem エラーメッセージ、処理結果の出力は最終的にはしないのでこの部分は消去予定 4mkdir .\log 5set BAT_LOG=%~dp0\log\%bad%.log 6 7mkdir .\test_all 8 9if "%~1"=="" goto usage 10 dir /a:d "%~1">NUL 2>&1 11 if %errorlevel% EQU 0 goto top 12 13 pushd "%~dp1" 14 "%~f0" "%CD%" 15 16:top 17set "pname=%~f1" 18set "name=%~nx1" 19 20for /f "delims=" %%f in ('dir /b "%cfname%"\*.csv') do ( 21 set "cfname=%%~dpf" 22 setlocal enabledelayedexpansion 23 for %%d in ("!cfname:~0,-1!") do ( 24 set "dirname=%%~nd" 25 copy "%pname%\%%f" ".\test_all\!dirname!_%%f" 26 ) 27 endlocal 28) 29 30goto :EOF 31 32:usage 33echo usage: %0 folder or file 34 35Pause 36Exit

=========以下8/14追記===========================

bat

1@echo off 2 3rem Cell_log_allフォルダを生成 4mkdir .\Cell_log_all 5 6rem 各Cell_log(CL-)サブフォルダを生成 7for %%i in (Mt-Log Df-Log Lf-Log Dd-Log) do ( 8 mkdir ".\Cell_log_all\CL-%%i" 9) 10 11setlocal enabledelayedexpansion 12 13rem フォルダ上から下へ 14for %%i in (Mt-Log Df-Log Lf-Log Dd-Log) do ( 15 rem サブフォルダカウント 16 set count=0 17 for /d %%j in ("%Cell_datalist%\%%i*") do ( 18 set /a count+=1 19 ) 20 21 rem サブフォルダ処理 22 for /d %%j in ("%Cell_datalist%\%%i*") do ( 23 set "sourceFolder=%%j" 24 set "destinationFolder=.\Cell_log_all\CL-%%i\%%~nxj" 25 26 rem サブフォルダコピー 27 xcopy /Y /I /E "!sourceFolder!" "!destinationFolder!" 28 ) 29) 30 31rem カレントフォルダCell_log_allフォルダ対象 32set "targetFolder=.\Cell_log_all" 33 34rem CSVファイル処理 35for /r "%targetFolder%" %%i in (*.csv) do ( 36 rem CSVファイルのパスを取得 37 set "csvPath=%%~fi" 38 39 rem フォルダ名変更 40 set "folderName=%%~dpi" 41 set "folderName=!folderName:~0,-1!" 42 43 rem ファイル名連結 CSVファイル移動 44 move /Y "!csvPath!" "!folderName!.csv" >nul 2>&1 45) 46 47rem 各サブフォルダ処理 48for %%i in (CL-Mt-Log CL-Df-Log CL-Lf-Log CL-Dd-Log) do ( 49 rem サブフォルダのパスを設定 50 set "subfolder=.\Cell_log_all\%%i" 51 52 rem 空フォルダ削除 53 for /d %%j in ("!subfolder!\*") do ( 54 rd "%%j" 2>nul 55 ) 56) 57 58endlocal 59 60exit

bat

1@echo off 2 3set "TargetFolder=%~dp1" 4 5rem Cell_log_allフォルダを生成 6mkdir .\Cell_log_all 7 8rem 各Cell_log(CL-)サブフォルダ生成 9for %%i in (Mt-Log Df-Log Lf-Log Dd-Log) do ( 10 mkdir ".\Cell_log_all\CL-%%i" 11) 12 13setlocal enabledelayedexpansion 14 15rem フォルダ上から下へ 16for %%i in (Mt-Log Df-Log Lf-Log Dd-Log) do ( 17 rem サブフォルダカウント 18 set count=0 19 for /d %%j in ("%TargetFolder%\%%i*") do ( 20 set /a count+=1 21 ) 22 23 rem サブフォルダ処理 24 for /d %%j in ("%TargetFolder%\%%i*") do ( 25 set "sourceFolder=%%j" 26 set "destinationFolder=.\Cell_log_all\CL-%%i\%%~nxj" 27 28 rem サブフォルダコピー 29 xcopy /Y /I /E "!sourceFolder!" "!destinationFolder!" 30 ) 31) 32 33rem カレントフォルダCell_log_allフォルダ対象 34set "targetFolder=.\Cell_log_all" 35 36rem CSVファイル処理 37for /r "%targetFolder%" %%i in (*.csv) do ( 38 rem CSVファイルのパスを取得 39 set "csvPath=%%~fi" 40 41 rem フォルダ名変更 42 set "folderName=%%~dpi" 43 set "folderName=!folderName:~0,-1!" 44 45 rem ファイル名連結 CSVファイル移動 46 move /Y "!csvPath!" "!folderName!.csv" >nul 2>&1 47) 48 49rem 各サブフォルダ処理 50for %%i in (CL-Mt-Log CL-Df-Log CL-Lf-Log CL-Dd-Log) do ( 51 rem サブフォルダのパスを設定 52 set "subfolder=.\Cell_log_all\%%i" 53 54 rem 空フォルダ削除 55 for /d %%j in ("!subfolder!\*") do ( 56 rd "%%j" 2>nul 57 ) 58) 59 60endlocal 61 62exit

試したこと

ファイル名を変更する等の単語で調べソースコードをお借りしてきたのち、ren→copy等のいくつかに変更を加えていきました。
各変数やコマンドの意味等を調べて理解を進めていました。

補足情報(FW/ツールのバージョンなど)

使用OS:windows10

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

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

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

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

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

otn

2023/08/10 05:47

21行目でcfnameにセットする前に20行目でcfnameを参照していますが、タイプミスでしょうか?
T_Sajispoon_T

2023/08/10 06:26

コメントありがとうございます。 こちらのミスになります、ごめんなさい。 set cfnameは19行目に記述しなければいけない...と思います。 ただ作成しているbatファイルも途中の状態であると同時に、当方もコードのどれがどう処理されているのかわからない状態になっているのが現状のため調べながら修正をしていきたいと思います。 ご指摘ありがとうございました。
otn

2023/08/10 06:35

引数指定で汎用にしようとしているようですが、まずは特定ディレクトリ(コードに埋め込み)でちゃんと動く物を作ってから、汎用化を考えるのが良いでしょう。
T_Sajispoon_T

2023/08/10 06:43

特定ディレクトリで~というのは処理を行いたいフォルダもしくはファイル自体を指定するという認識でよろしいでしょうか?
otn

2023/08/10 08:41 編集

はい。 いまのスクリプトをそのままそのように書き換えて動くようになるわけじゃないですが、 考えないと行けないことが減るので、考えているときの間違いの発生が減ります。 今のを全部消して、忘れて、ゼロから書き直すのが良いと思います。
T_Sajispoon_T

2023/08/10 08:45

わかりました、ありがとうございます、頑張ってみます。
guest

回答1

0

ベストアンサー

方法としては、
案1:test_listAなどについてのループの中で、test_listA202308などについてのループを回るという二重ループにする。
案2:絶対パスの一覧を作り、絶対パスを\で分割して必要な情報を取り出す。
などが考えられます。質問文のコードはおそらく案1をやろうとしている途中。
案2でいくと、下記のような感じです。

仮に、bat_test の場所を D:\foo\bar\bat_test だとすると、%%Fの対象ファイル名は、
D:\foo\bar\bat_test\test_listA\test_listA202308\datalist01.csv
等で、使いたい名前は、\で分割した6、7番目なので、

CMD

1pushd D:\Temp\Z\bat_test 2for /f "delims=" %%F in ('dir /b /s *.csv') do ( 3 for /f "delims=\ tokens=6,7" %%X in ("%%~F") do ( 4 copy "%%~F" "..\test_all\%%X%%Y" 5 ) 6)

質問文中のディレクトリー構造だけは固定だが、場所を D:\foo\bar\bat_test のように特定したくないと言うことなら、
(=異なる場所の時に、6,7を数え直して修正したくないなら)
前半のドライブ名からbat_testまでの部分(%CD%相当)を削除すると、
test_listA\test_listA202308\datalist01.csv
と、2、3番目に確定します。

CMD

1setlocal enabledelayedexpansion 2pushd %~dp0\bat_test 3for /f "delims=" %%F in ('dir /b /s *.csv') do ( 4 set "FN=%%F" 5 set "FN=!FN:%CD%\=!" 6 for /f "delims=\ tokens=2,3" %%X in ("!FN!") do ( 7 copy "!FN!" "..\test_all\%%X%%Y" 8 ) 9)

追記

階層を1つ見誤っていたので、コードを下記のように訂正しておきます。

CMD

1setlocal enabledelayedexpansion 2pushd %~dp0\bat_test 3for /f "delims=" %%F in ('dir /b /s *.csv') do ( 4 set "FN=%%F" 5 set "FN=!FN:%CD%\=!" 6 for /f "delims=\ tokens=1,2,3" %%X in ("!FN!") do ( 7 if not exist "..\test_all\%%X" mkdir "..\test_all\%%X" 8 copy "!FN!" "..\test_all\%%X\%%Y%%Z" 9 ) 10)

~~~\bat_test\test_listA\test_listA202308\datalist01.csvといいうファイルに対して、
%%X ・・・ test_listA
%%Y ・・・ test_listA202308
%%Z ・・・ datalist01.csv
ですね。
bat_test相当をドロップするなら、最初のところをpushd %1にすればその隣にtest_allが出来ます。

投稿2023/08/10 09:05

編集2023/08/14 11:50
otn

総合スコア86295

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

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

T_Sajispoon_T

2023/08/14 11:16

返信遅くなり大変申し訳ありません、アドバイスありがとうございます。 otnさんから頂いたコードを組み込んでコードの作成を続けていましたが、力足らず正常に動作させることができませんでした。申し訳ありません。 過去コメントいただいた通り、一度最初からコードを書き直してみた結果、省略できる箇所があるとは思いますが、フォルダを一つに指定して実行処理を行うことはできました。しかし、実行するフォルダを指定しない場合を作成したものの上手くいっていない状態です。大変恐縮なのですが、再度アドバイスいただけたら幸いです。 重ねて今回、アドバイスをいただきありがとうございました。
otn

2023/08/14 11:53

> otnさんから頂いたコードを組み込んでコードの作成を続けていましたが、 回答のコードは、階層を1つ飛ばしていたので、訂正しておきました。 お書きのコードは仕様が分からないので、書いて貰えば読みます。 どういうフォルダー・ファイル構成で、そのうちのどのフォルダーをドロップしたら、結果としてどういうフォルダー・ファイル構成にしたいかなど。
T_Sajispoon_T

2023/08/14 12:41 編集

コメントありがとうございます。 仕様...は書いたことがないので処理で行いたいことを挙げていこうと思います。 前述したとおり、一旦コードをはじめから考え直しました。 フォルダ構成と新しく作ったコードは下記になります。 やりたいことを簡単にまとめますと「バッチファイルを実行したフォルダ内に存在するすべてのcsvファイルを各種類ごとのフォルダにまとめる。」になります。 そして今回新しく作り直したコードでは ①コピー先フォルダの作成 ②コピー先フォルダにサブフォルダ作成 ③csvファイルを含んだフォルダのコピー ④csvファイルのリネーム及び移動 ⑤空になったフォルダの削除 をしています。 これの先はさらに 実行処理した複数のフォルダの 各フォルダのMt-Log、Df-Log、Lf-Log、Dd-Logをそれぞれ一つにまとめていく...といったことをしようとしています。 ((質問自体を編集して追記しております。)) フォルダ構成 ``` Folder 親フォルダ/ ├─作成するバッチファイル/ ├─バッチファイルで実行したいフォルダ/(※今回指定したフォルダは「Cell_datalist」)←他にも処理をしたいフォルダが複数ある │  ├─Mt-Log/ │  │  ├─ Mt-Log20230801/ │  │  │  └─ datalog.csv │  │  ├─ Mt-Log20230808/ │  │  │  └─ datalog.csv │  │  ├─ Mt-Log20230815/ │  │  │  └─ datalog.csv │  │  └─ ... │  │ │  ├─ Df-Log/ │  │  ├─ Df-Log20230801/ │  │  │  └─ datalog.csv │  │  ├─ Df-Log20230808/ │  │  │  └─ datalog.csv │  │  ├─ Df-Log20230815/ │  │  │  └─ datalog.csv │  │  └─ ... │  │ │  │ │  ├─ Lf-Log/ │  │  ├─ Lf-Log20230801/ │  │  │  └─ datalog.csv │  │  ├─ Lf-Log20230808/ │  │  │  └─ datalog.csv │  │  ├─ Lf-Log20230815/ │  │  │  └─ datalog.csv │  │  └─ ... │  │ │  │ │  └─ Dd-Log/ │     ├─ Dd-Log20230801/ │     │  └─ datalog.csv │     ├─ Dd-Log20230808/ │     │  └─ datalog.csv │     ├─ Dd-Log20230815/ │     │  └─ datalog.csv │     └─ ... │   │ └─ Cell_log_all/(バッチファイル実行後に作成されるフォルダ、および処理したCSVファイルを格納するフォルダ)    ├─CL-Mt-Log/    │  ├─ Mt-Log20230801datalog.csv    │  ├─ Mt-Log20230808datalog.csv    │  ├─ Mt-Log20230815datalog.csv    │  └─ ...    │    ├─ CL-Df-Log/    │  ├─ Df-Log20230801datalog.csv    │  ├─ Df-Log20230808datalog.csv    │  ├─ Df-Log20230815datalog.csv    │  └─ ...    │    ├─ CL-Lf-Log/    │  ├─ Lf-Log20230801datalog.csv    │  ├─ Lf-Log20230808datalog.csv    │  ├─ Lf-Log20230815datalog.csv    │  └─ ...    │    └─ CL-Dd-Log/       ├─ Dd-Log20230801datalog.csv       ├─ Dd-Log20230808datalog.csv       ├─ Dd-Log20230815datalog.csv       └─ ... ``` ``` CMD @echo off rem Cell_log_allフォルダを生成 mkdir .\Cell_log_all rem 各Cell_log(CL-)サブフォルダを生成 for %%i in (Mt-Log Df-Log Lf-Log Dd-Log) do ( mkdir ".\Cell_log_all\CL-%%i" ) setlocal enabledelayedexpansion rem フォルダ上から下へ for %%i in (Mt-Log Df-Log Lf-Log Dd-Log) do ( rem サブフォルダカウント set count=0 for /d %%j in ("%Cell_datalist%\%%i*") do ( set /a count+=1 ) rem サブフォルダ処理 for /d %%j in ("%Cell_datalist%\%%i*") do ( set "sourceFolder=%%j" set "destinationFolder=.\Cell_log_all\CL-%%i\%%~nxj" rem サブフォルダコピー xcopy /Y /I /E "!sourceFolder!" "!destinationFolder!" ) ) rem カレントフォルダCell_log_allフォルダ対象 set "targetFolder=.\Cell_log_all" rem CSVファイル処理 for /r "%targetFolder%" %%i in (*.csv) do ( rem CSVファイルのパスを取得 set "csvPath=%%~fi" rem フォルダ名変更 set "folderName=%%~dpi" set "folderName=!folderName:~0,-1!" rem ファイル名連結 CSVファイル移動 move /Y "!csvPath!" "!folderName!.csv" >nul 2>&1 ) rem 各サブフォルダ処理 for %%i in (CL-Mt-Log CL-Df-Log CL-Lf-Log CL-Dd-Log) do ( rem サブフォルダのパスを設定 set "subfolder=.\Cell_log_all\%%i" rem 空フォルダ削除 for /d %%j in ("!subfolder!\*") do ( rd "%%j" 2>nul ) ) endlocal exit ``` 以上が今回書き直したコードになります、このコード自体は動いたのですが、 バッチファイルを実行するフォルダを名称指定ではなく、実行したファイル自体を指定したく `set "TargetFolder=%~dp1"` の追加と一部の修正をしたのですが上記コード14行目以降`for %%i in (Mt-Log Df-Log Lf-Log Dd-Log) do (...` の処理がうまくいかなくなったところで止まっている状態になります。 情報をうまく伝えれていないかもしれませんがご確認のほどよろしくお願いいたします。
otn

2023/08/14 15:06

こういうのは、コメントじゃなくて、質問に書きましょう。
T_Sajispoon_T

2023/08/15 06:57

失礼しました、改めて新しく質問を投稿します。
otn

2023/08/15 09:27

いや、新しい質問じゃなくて、今の質問を騙取します。 新しく質問を立てると、「過去に投稿した質問と同じ質問」という指摘を受けます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問