• ベストアンサー

batの検証依頼

現在、batを作成中です。 ターゲットが巨大HDD(2TB)のディスクをbatで読み込んで処理中ですが 処理時間が10分程度必要なのでHDDで何度もトライ&エラーで処理するのは効率的ではありません。 しかも、処理を何度も行うとHDDに負担がかかる。 そこで、以下のコードで問題ないか コードを検証してもらえないでしょうか? 長い文字列(フルパス)が何度も出てきて読みにくいので変数で処理すべきでしょうが 自分のコード作成能力上間違いが少ない方法を選んでいます。 コメントをたくさん入れたのでどんな事をやりたいかはご理解願えると思いますが 不明な点は追加で説明いたします。 コードに不都合な点あれば、修正していただければ幸いです。 ’-------------------------------------------------------------------- REM ドライブレターの全フォルダー名のみを階層を含めて出力 REM ドライブ直下のファイル名(フルパス)の出力にも対応 REM ---------------------------------------------------- @echo off set /p D="ドライブを入力してください <例> x --> " cd /d %D%: REM サーチ先のドライブに移動して以下の作業を行う(書き出しもサーチ先になる) REM -- ドライブレターの全フォルダー名のみを階層を含めて出力 REM -- ドライブ直下のファイル名は出力しない dir /b /ad /s>temp1.txt REM -- /d ドライブ直下のファイル名のみを出力 (a-d ドライブ直下のファイル名のみ出力) dir /b /d >temp2.txt REM ファイル結合してコピー REM C:\UsersTAC_\Desktop\Mp3_MergeDrive\ ---> BATがあるフォルダを表す copy /Y temp2.txt + temp1.txt C:\UsersTAC_\Desktop\Mp3_MergeDrive\temp.txt REM tempファイル削除 del /Q temp1.txt del /Q temp2.txt REM 出力ファイルをソート sort /o C:\UsersTAC_\Desktop\Mp3_MergeDrive\temp.txt C:\UsersTAC_\Desktop\Mp3_MergeDrive\temp.txt rename C:\UsersTAC_\Desktop\Mp3_MergeDrive\temp.txt C:\UsersTAC_\Desktop\Mp3_MergeDrive\FileName_ListUp.txt REM ------------------------------------------------ REM Vol1, Vol2, Vol3という変数にボリューム名をセット set Vol1=K-N set Vol2=456 set Vol3=789 REM IDという変数を空でセット set ID= REM wmicコマンドでHDDのvolumenumberを取得し、findコマンドでVol1, Vol2, Vol3の値を検索 REM errorlevelの値に応じて、IDという変数にX, Y, Zの値をセット wmic logicaldisk get volumename | find "%Vol1%" if errorlevel 0 if not errorlevel 1 set ID=X wmic logicaldisk get volumename | find "%Vol2%" if errorlevel 0 if not errorlevel 1 set ID=Y wmic logicaldisk get volumename | find "%Vol3%" if errorlevel 0 if not errorlevel 1 set ID=Z REM 調査結果の表示、numの値で、serialnumberの中に一致するものがあったため、ID=X,Y,Zを表示。 REM serialnumberの中に一致するものがなかった場合、IDには何もセットせずに表示。 if defined ID ( echo Match found. ID=%ID% ) else ( echo No match found. ID=%ID% REM ドライブを加味したファイル名に変名 if defined ID rename C:\UsersTAC_\Desktop\Mp3_MergeDrive\FileName_ListUp.txt C:\UsersTAC_\Desktop\Mp3_MergeDrive\%ID% _FileName_ListUp.txt cls & echo "終了しました" & pause exit /b

質問者が選んだベストアンサー

  • ベストアンサー
  • luka3
  • ベストアンサー率72% (424/583)
回答No.8

毎回、いいタイミングですれ違いがおこっているようで。 >しかし、なぜだか変名はされて、「X_FileName_ListUp.txt」は作成されています。 なぜだかも何も、その前の「 if defined ID ( 」のところですでに rename されてるからです。 どちらか一つを生かして、もう一方は消しましょう。

NuboChan
質問者

お礼

お陰様でコードを修正して  16GBのお試し用のフラッシュメモリーでエラー無く処理できるようになりました。  一度、実HDDで試用して約3分でエラー無く処理完了しました これで自分では完成まで行きついたと思いますが  何か他に気になる点やアドバイスがありますか? 修正箇所 :  renameは上書きできないのでmoveに変更しました。  ゴミ箱とドライブ内のゴミ箱の中身をクリアするようにしました。  (お試しのフラッシュメモリーでは必要ありませんがターゲットのHDDでは必要) アドバイスにある batでドライブ名を入れる案は、接続するHDDを間違えた場合でも 処理出来てしまうのでHDDに記載したボリュームラベルを利用する 現在の方法を使いたいと思います。 REM ドライブレターの全フォルダー名のみを階層を含めて出力 REM ドライブ直下のファイル名(フルパス)の出力にも対応 REM ---------------------------------------------------- @echo on set /p D="ドライブを入力してください <例> K --> " REM 「cd D:\フォルダー名」と入力することで、現在のディレクトリであるDドライブの特定のフォルダーにアクセスすることができます。 REM しかし、現在の作業ドライブやディレクトリがCドライブである場合、このコマンドは機能しません。 REM その場合は、コマンドプロンプトでCDコマンドを使わずに、コマンド「cd /d d:」を使用します。 REM このコマンドを実行すると、現在のDドライブのディレクトリに移動し、現在のドライブもDドライブに変更されます。 cd /d %D%: REM ゴミ箱とドライブ内のゴミ箱の中身をクリア rd /s /q %D%:\$Recycle.Bin REM サーチ先のドライブに移動して以下の作業を行う(書き出しもサーチ先になる) REM -- ドライブレターの全フォルダー名のみを階層を含めて出力 REM /b : ファイルやディレクトリ名のみ (要約や日時、サイズなどを省略) REM /ad : フォルダ名のみ REM /s : 指定したディレクトリおよびそのサブディレクトリ(階層も含める) dir /b /ad /s > C:\temp\temp1.txt REM -- /a-d ドライブ直下のファイル名のみを出力 dir /b /a-d > C:\temp\temp2.txt REM ファイル結合してコピー テキストで書き出す。 デフォルト --> Copy /a copy /a C:\temp\temp2.txt + C:\temp\temp1.txt C:\temp\temp.txt REM tempファイル削除(del /Q --> 確認メッセージが表示されずに DEL コマンドを実行) del /Q C:\temp\temp1.txt del /Q C:\temp\temp2.txt REM 出力ファイルをソート sort /o C:\temp\FileName_ListUp.txt C:\temp\temp.txt REM シート前のファイルは削除(del /Q --> 確認メッセージが表示されずに DEL コマンドを実行) del /Q C:\temp\temp.txt REM ------------------------------------------------ REM Vol1, Vol2, Vol3という変数にボリューム名をセット set Vol1=K-N set Vol2=456 set Vol3=789 REM IDという変数を空でセット set ID= REM wmicコマンドでHDDのvolumenumberを取得し、findコマンドでVol1, Vol2, Vol3の値を検索 REM errorlevelの値に応じて、IDという変数にX, Y, Zの値をセット wmic logicaldisk get volumename | find "%Vol1%" if %errorlevel% EQU 0 set ID=X wmic logicaldisk get volumename | find "%Vol2%" if %errorlevel% EQU 0 set ID=Y wmic logicaldisk get volumename | find "%Vol3%" if %errorlevel% EQU 0 set ID=Z REM 調査結果の表示、numの値で、serialnumberの中に一致するものがあった場合、ID=X,Y,Zを表示し REM ドライブを加味したファイル名に変名。 REM 変名にrenameを使うと上書きが出来ないのでmoveを使用(オプションなしでは上書き確認無し) REM serialnumberの中に一致するものがなかった場合、IDには何もセットせずに表示。 if defined ID ( echo Match found. ID=%ID% move C:\temp\FileName_ListUp.txt C:\temp\%ID%_FileName_ListUp.txt ) else ( echo No match found. ID=%ID% ) echo. echo " ---- 処理が終了しました。 -----" & pause exit /b

その他の回答 (7)

  • luka3
  • ベストアンサー率72% (424/583)
回答No.7

事情、了解しました。 では、そのドライブのボリュームラベルをファイル名に入れるというのはどうでしょう。 最初に入力するドライブ名は大文字で入れるという前提で for /f "tokens=2,3 delims=," %I in ('wmic logicaldisk get name^,volumename /format:csv') do if "%I"=="%D%:" set "VOL=%J" if defined VOL ( rename C:\Users\TAC_\Desktop\Mp3_MergeDrive\FileName_ListUp.txt "%VOL%_FileName_ListUp.txt" ) else ( echo ボリュームラベルが見つかりませんでした。ドライブ名を大文字で入れましたか? )

  • luka3
  • ベストアンサー率72% (424/583)
回答No.6

No.4お礼より、 「 ) else ( 」のペアになる ) がないのが原因です。 これ以降のコマンドが、「IDが定義されていない場合」にのみ実行されるためです。 こういった時の動作確認方法としては、最初の @echo off を消すか on にして、どういう流れでコマンドが実行されているかを追ってみるといいです。

NuboChan
質問者

お礼

ありがとうございます。 アドバイスを受けて不備なコードを修正し検証途中です。 後半部のコードをそのまま反映してみましたが  最後の変名の部分で添付画像のようにエラーがでます。      添付画像  https://imgur.com/BeK5tUn しかし、なぜだか変名はされて、「X_FileName_ListUp.txt」は作成されています。 以下現在のコードです。 REM ドライブレターの全フォルダー名のみを階層を含めて出力 REM ドライブ直下のファイル名(フルパス)の出力にも対応 REM ---------------------------------------------------- @echo on set /p D="ドライブを入力してください <例> K --> " REM 「cd D:\フォルダー名」と入力することで、現在のディレクトリであるDドライブの特定のフォルダーにアクセスすることができます。 REM しかし、現在の作業ドライブやディレクトリがCドライブである場合、このコマンドは機能しません。 REM その場合は、コマンドプロンプトでCDコマンドを使わずに、コマンド「cd /d d:」を使用します。 REM このコマンドを実行すると、現在のDドライブのディレクトリに移動し、現在のドライブもDドライブに変更されます。 cd /d %D%: REM サーチ先のドライブに移動して以下の作業を行う(書き出しもサーチ先になる) REM -- ドライブレターの全フォルダー名のみを階層を含めて出力 REM /b : ファイルやディレクトリ名のみ (要約や日時、サイズなどを省略) REM /ad : フォルダ名のみ REM /s : 指定したディレクトリおよびそのサブディレクトリ(階層も含める) dir /b /ad /s > C:\temp\temp1.txt REM -- /a-d ドライブ直下のファイル名のみを出力 dir /b /a-d > C:\temp\temp2.txt REM ファイル結合してコピー テキストで書き出す。 デフォルト --> Copy /a copy /a C:\temp\temp2.txt + C:\temp\temp1.txt C:\temp\temp.txt REM tempファイル削除(del /Q --> 確認メッセージが表示されずに DEL コマンドを実行) del /Q C:\temp\temp1.txt del /Q C:\temp\temp2.txt REM 出力ファイルをソート sort /o C:\temp\FileName_ListUp.txt C:\temp\temp.txt REM シート前のファイルは削除(del /Q --> 確認メッセージが表示されずに DEL コマンドを実行) del /Q C:\temp\temp.txt REM ------------------------------------------------ REM Vol1, Vol2, Vol3という変数にボリューム名をセット set Vol1=K-N set Vol2=456 set Vol3=789 REM IDという変数を空でセット set ID= REM wmicコマンドでHDDのvolumenumberを取得し、findコマンドでVol1, Vol2, Vol3の値を検索 REM errorlevelの値に応じて、IDという変数にX, Y, Zの値をセット wmic logicaldisk get volumename | find "%Vol1%" if %errorlevel% EQU 0 set ID=X wmic logicaldisk get volumename | find "%Vol2%" if %errorlevel% EQU 0 set ID=Y wmic logicaldisk get volumename | find "%Vol3%" if %errorlevel% EQU 0 set ID=Z REM 調査結果の表示、numの値で、serialnumberの中に一致するものがあった場合、ID=X,Y,Zを表示。 REM serialnumberの中に一致するものがなかった場合、IDには何もセットせずに表示。 if defined ID ( echo Match found. ID=%ID% rename C:\temp\FileName_ListUp.txt %ID%_FileName_ListUp.txt ) else ( echo No match found. ID=%ID% ) REM ドライブを加味したファイル名に変名 if defined ID rename C:\temp\FileName_ListUp.txt C:\temp\%ID%_FileName_ListUp.txt echo "処理が終了しました。" & pause exit /b

  • luka3
  • ベストアンサー率72% (424/583)
回答No.5

自分も考えてみました。 set /p D="ドライブを入力してください <例> x --> " dir /b /ad /s %D%:\ >%TEMP%\temp.txt dir /b /d %D%:\ >>%TEMP%\temp.txt sort /o C:\Users\TAC_\Desktop\Mp3_MergeDrive\FileName_ListUp.txt %TEMP%\temp.txt del /Q %TEMP%\temp.txt set Vol1=K-N set Vol2=456 set Vol3=789 REM IDという変数を【リセット】 set ID= wmic logicaldisk get volumename | find "%Vol1%" if %errorlevel% EQU 0 set ID=X wmic logicaldisk get volumename | find "%Vol2%" if %errorlevel% EQU 0 set ID=Y wmic logicaldisk get volumename | find "%Vol3%" if %errorlevel% EQU 0 set ID=Z if defined ID ( echo Match found. ID=%ID% rename C:\Users\TAC_\Desktop\Mp3_MergeDrive\FileName_ListUp.txt %ID%_FileName_ListUp.txt ) else ( echo No match found. ID=%ID% ) echo "終了しました" & pause exit /b 最後 cls すると Match found が確認できないので消してます。 ところで、%ID% って、%D% じゃないんですかね? もしそうなら、 「set /p D="ドライブを大文字で入力してください <例> X --> "」 とすれば、4行目から 「sort /o C:\Users\TAC_\Desktop\Mp3_MergeDrive\%D%_FileName_ListUp.txt %TEMP%\temp.txt  del /Q %TEMP%\temp.txt 」 で以下削除になると思います。

NuboChan
質問者

お礼

luka3さん、コードをありがとうございます。 まず、 「%ID% って、%D% じゃないんですかね?」問題から %ID%は%D%の間違いではありません。 まず、後半のbatの作成にいたる経緯を長くなりますが書きます。 同じコードで同じUSB端子で3つのHDD(X,Y,Z)を順番に3回処理する予定です。 そうなるとドライブレターが全て同じなので 理論上は FileName_ListUp.txtはテキスト内容が異なる3つの同名ファイルが出来上がる事になります。 3つの同名ファイルは、最終的には結合されて1つのファイルになる予定ですが 当然ファイル名が同一なのでこのままでは結合できません。 なのでFileName_ListUp.txtが出力されるとファイル名を手動で3回変名する必要があります。 この変名もbatで処理したくドライブ(X,Y,Z)を個別にボリューム名を自動判断して ファイル名に付加する事を考えました。 ’------------------------- 今から、頂いたコードの検証を始めます。 結果は出来るだけ早く上げる予定ですがそれまで少し時間をください。

回答No.4

> パスがユ-ーザー以下では問題があるのですか ? 問題ないと思いますが、単純に記述ミスがないか、確認してください。 > forコードを使うと作動が遅くなると認識しています。 ルートのファイル一覧を取得するためだけにforを使っています。 ふつう、ルートにはそんなにファイルは大量に置かないかなと思いますので、気にしなくて良いかと。 (ルートにファイルがたくさんあるなら、フォルダを作って移動させることを推奨)

NuboChan
質問者

お礼

ありがとうございます。 for文の件は、理解できました。 コードの不備がありましたのでコードを修正しています。 コードで以下のREMまでは作動確認がとれたました。 REM 確認済み ------------------------------------------------ しかしそれ以後のコードで findコマンドでVol1, Vol2, Vol3の値を検索してヒットすれば変数のIDにX,Y,Zを代入する 以降が上手く処理できていません。 どこか?間違いがあるので修正をお願いします。 最後から1及び2番目のpauseで一時停止しませんし最後の変名が出来ずに終了する。 REM ドライブレターの全フォルダー名のみを階層を含めて出力 REM ドライブ直下のファイル名(フルパス)の出力にも対応 REM ---------------------------------------------------- @echo off set /p D="ドライブを入力してください <例> K --> " REM 「cd D:\フォルダー名」と入力することで、現在のディレクトリであるDドライブの特定のフォルダーにアクセスすることができます。 REM しかし、現在の作業ドライブやディレクトリがCドライブである場合、このコマンドは機能しません。 REM その場合は、コマンドプロンプトでCDコマンドを使わずに、コマンド「cd /d d:」を使用します。 REM このコマンドを実行すると、現在のDドライブのディレクトリに移動し、現在のドライブもDドライブに変更されます。 cd /d %D%: REM サーチ先のドライブに移動して以下の作業を行う(書き出しもサーチ先になる) REM -- ドライブレターの全フォルダー名のみを階層を含めて出力 REM /b : ファイルやディレクトリ名のみ (要約や日時、サイズなどを省略) REM /ad : フォルダ名のみ REM /s : 指定したディレクトリおよびそのサブディレクトリ(階層も含める) dir /b /ad /s > C:\temp\temp1.txt REM -- /a-d ドライブ直下のファイル名のみを出力 dir /b /a-d > C:\temp\temp2.txt REM ファイル結合してコピー テキストで書き出す。 デフォルト --> Copy /a copy /a C:\temp\temp2.txt + C:\temp\temp1.txt C:\temp\temp.txt REM tempファイル削除(del /Q --> 確認メッセージが表示されずに DEL コマンドを実行) del /Q C:\temp\temp1.txt del /Q C:\temp\temp2.txt REM 出力ファイルをソート sort /o C:\temp\FileName_ListUp.txt C:\temp\temp.txt REM 確認済み ------------------------------------------------ REM Vol1, Vol2, Vol3という変数にボリューム名をセット set Vol1=K-N set Vol2=456 set Vol3=789 REM IDという変数を空でセット set ID= REM wmicコマンドでHDDのvolumenumberを取得し、findコマンドでVol1, Vol2, Vol3の値を検索 REM errorlevelの値に応じて、IDという変数にX, Y, Zの値をセット wmic logicaldisk get volumename | find "%Vol1%" if errorlevel 0 if not errorlevel 1 set ID=X wmic logicaldisk get volumename | find "%Vol2%" if errorlevel 0 if not errorlevel 1 set ID=Y wmic logicaldisk get volumename | find "%Vol3%" if errorlevel 0 if not errorlevel 1 set ID=Z REM 調査結果の表示、numの値で、serialnumberの中に一致するものがあったため、ID=X,Y,Zを表示。 REM serialnumberの中に一致するものがなかった場合、IDには何もセットせずに表示。 if defined ID ( echo Match found. ID=%ID% ) else ( echo No match found. ID=%ID% pause REM ドライブを加味したファイル名に変名 if defined ID rename C:\temp\FileName_ListUp.txt C:\temp\%ID% _FileName_ListUp.txt echo "処理が終了しました。" pause exit /b

回答No.3

@echo off set target=D:\ cd /d %target% del c:\temp\files2.txt dir /b /s /ad /on > c:\temp\files.txt for %%f in (*) do ( echo %target%%%f >> c:\temp\files2.txt ) type c:\temp\files2.txt | sort >> c:\temp\files.txt del c:\temp\files2.txt echo on こんな感じでどうでしょう?前もって、c:\temp というフォルダを作ってからbatを実行してみてください。

NuboChan
質問者

お礼

コードをありがとうございます。 コードは作動しました。 ただ、最初の以下のコードは必要ないと思います。 (存在しないfiles2を削除しようとしてもエラー) del c:\temp\files2.txt どうもbatの動作がおかしいのでお伺いしたいのですが、 c:\temp ではなく C:\Users\TAC_\Desktop\Mp3_MergeDrive\でbatを作成して実行すると files2.txtが作成されて残されていてfiles1.txtが存在しません。 パスがユ-ーザー以下では問題があるのですか ? それと私は、forコードを使うと作動が遅くなると認識しています。 実際のターゲットのHDDは2TBもあるのでforコードの利用には抵抗があります。 認識に間違いがありますか ?

NuboChan
質問者

補足

すいません。 記載に間違いがあります。 以下に訂正します。 files2.txtが作成されて残されていてfiles.txtが存在しません。

回答No.2

コードの検証は識者にお任せするとして、いきなりターゲットの2TBのHDDではなく、小容量のUSBメモリでトライ&エラーしてみてはいかがでしょうか?

NuboChan
質問者

お礼

アドバイスありがとうございます。 最初から巨大HDDは無謀ですね。 アドバイスを受けて テスト用の16GBのドライブにドライブ名を付けて そこから検証を始めます。

回答No.1

cd /d d:\ attrib /s > c:\temp\list.txt というコマンドで c:\temp\list.txt に d:\ 以下の全ファイルがフルパスで出力されますよ。(ファイル属性も出力されますが)

NuboChan
質問者

お礼

回答ありがとうございます。 >cd /d d:\ >attrib /s > c:\temp\list.txt フルパスのファイル名や属性は必要ありません。 必要なのは、以下です。  ドライブレターの全フォルダー名(階層考慮)  ドライブ直下のファイル名のみ

関連するQ&A