時間がかかるバッチ処理をするときに、コマンドプロンプトの画面にプログレスバー(進捗状況)を表示する方法です。
処理する総数を指定、もしくは取得して、処理が完了した割合に応じてバーを表示します。
目次
1. バーを表示する方法
1-1. バーを表示するバッチ
まず初めに、バーを表示する部分のみを抜き出したバッチで解説していきます。
下記のバッチを実行すると、「Total」に指定した回数だけ処理が行われ、その割合に応じて「■」が20個並んでいきます。
@echo off
setlocal enabledelayedexpansion
set /a Total=5000
set /a Rate=0
set /a Display=1
for /l %%i in (1,1,%Total%) do (
set /a Rate=%%i * 20
set /a Rate/=%Total%
if !Rate! geq !Display! (
set /p Bar=■< nul
set /a Display+=1
)
)
echo. & pause
1-2. 使用する変数と解説
- Total … 処理する総数。ここでは例として5000を指定。
- Rate … Total に対する割合を、0~20の整数で表す。20で100%。
- Display … 「■」を表示する閾値。Rate が Display の値に届いたら表示。1~20の整数。
20個の「■」でバーを表現するために、Rate も Display も20までの整数で表します。
20個ということは5%ごとに1つ表示されますので、Rate を数学的に表現すると次のようになります。
- Rate = {%%i(処理番号) ÷ Total} × 100(%に換算) ÷ 5(5%刻み)
上記のバッチではこれを整数で取得し、Display の値と等しくなったら「set /p Bar=■< nul」のところで「■」を1つ表示しています。
「set」コマンドの「/p」はユーザーの入力待ちができるオプションですが、入力カーソルの前に文字を表示できるので、それを利用しています。
「< nul」で何も入力しない指示をして、実際には「■」が表示されるだけのコマンドになっています。
表示後は Display の値に1を足して閾値を上げ、次に Rate が届くまで表示せずにループすることを繰り返します。
これらの計算を「for」コマンドの中で行うために、バッチの2行目で「setlocal enabledelayedexpansion」を指定しています。
1-3. ループ処理について
プログレスバーが必要になるのは、膨大な数の処理を行う場合か、回数はそれほど多くなくても1つ1つの処理が重い場合だと思います。
どちらにしてもループ処理が入るバッチだと考えられますので、そのループの中にバーの表示を組み込むことになります。
上記のバッチでは、「for」の「/l」オプションを使って1から Total までの数を繰り返しています。
オプションによって組み込み方は変わるものの、「Total」に対する割合を「Rate」に取得して「Display」と比較する、という基本は一緒です。
ループ処理については「goto」コマンドとラベルを使った方法もありますが、「for」コマンドを使った方が圧倒的に処理速度が速いので、可能な限り「for」に組み込むことを考えましょう。
実際の処理内容が軽ければ、「for」で1000回程度ならほぼ一瞬で終わります。これを「goto」で行うと数秒かかります。
2. 回数を指定して処理を行うバッチの例
2-1. 回数指定バッチ
それでは、実際に組み込んだバッチを見ていきましょう。といっても、処理内容は空欄にしてあります。
30行目の「処理内容」の直後に、実際の処理を書いて使います。
@echo off
setlocal enabledelayedexpansion
echo [進捗状況]
echo 0 50 100(%%)
echo ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
set /p Bar=_< nul
rem ==========処理回数設定==========
set /a Total=1000
rem ----------Totalのチェック----------
if "%Total%" == "" (
echo. & echo. & echo エラー: 処理回数を正しく設定してください。
pause > nul & exit /b
)
if %Total% lss 1 (
echo. & echo. & echo エラー: 処理回数を正しく設定してください。
pause > nul & exit /b
) else if %Total% lss 20 (
set /a PreBar=20 - %Total%
for /l %%i in (1,1,!PreBar!) do (set /p Bar=■< nul)
)
rem ----------処理開始----------
set /a Rate=0
set /a Display=1
for /l %%i in (1,1,%Total%) do (
rem ==========処理内容(Totalの数だけ繰り返す処理)==========
rem ----------バー表示----------
set /a Rate=%%i * 20
set /a Rate/=%Total%
if !Rate! geq !Display! (
set /p Bar=■< nul
set /a Display+=1
)
)
echo. & echo. & echo 処理が完了しました。
pause > nul & exit /b
2-2. 補足説明
echo [進捗状況]
echo 0 50 100(%%)
echo ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
set /p Bar=_< nul
プログレスバーは20個の「■」で表現しますが、スケールとなる罫線がないとわかりにくいので、最初に表示しています。この部分は罫線を実際に表示しながら作成しました。
罫線の下で半角ずらさないと「■」の位置と合わないため、「Bar=_」でずらしています。
if "%Total%" == "" (
echo. & echo. & echo エラー: 処理回数を正しく設定してください。
pause > nul & exit /b
)
if %Total% lss 1 (
echo. & echo. & echo エラー: 処理回数を正しく設定してください。
pause > nul & exit /b
) else if %Total% lss 20 (
set /a PreBar=20 - %Total%
for /l %%i in (1,1,!PreBar!) do (set /p Bar=■< nul)
)
「Total」が空欄もしくは1未満の場合への対応をした後、20未満の場合の処理をしています。
20未満だとプログレスバーが埋まらず見た目が良くないため、先に不足分を「PreBar」に取得してバーを埋めています。
3. フォルダ内の各ファイルに対して処理を行うバッチの例
3-1. 各ファイル処理バッチ
@echo off
setlocal enabledelayedexpansion
echo [進捗状況]
echo 0 50 100(%%)
echo ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
set /p Bar=_< nul
rem ----------ファイル数取得----------
set /a Total=0
for %%i in (*.*) do (set /a Total+=1)
rem ----------Totalのチェック----------
if %Total% lss 20 (
set /a PreBar=20 - %Total%
for /l %%i in (1,1,!PreBar!) do (set /p Bar=■< nul)
)
rem ----------処理開始----------
set /a Rate=0
set /a Display=1
set /a Num=1
for %%i in (*.*) do (
if not %%i == %~nx0 (
rem ==========処理内容(%%iに入った各ファイルに対する処理)==========
)
rem ----------バー表示----------
set /a Rate=!Num! * 20
set /a Rate/=%Total%
if !Rate! geq !Display! (
set /p Bar=■< nul
set /a Display+=1
)
set /a Num+=1
)
echo. & echo. & echo 処理が完了しました。
pause > nul & exit /b
3-2. 補足説明
rem ----------ファイル数取得----------
set /a Total=0
for %%i in (*.*) do (set /a Total+=1)
ここではフォルダ内のファイル数を取得して「Total」に格納しています。
「for」コマンドをオプションなしで使い、ファイルの数だけ「Total」に1を足すことで取得します。
ファイルの数だけ繰り返すので処理速度が気になるところですが、上述した通り「for」は非常に速いので全く問題ありません。
ちなみに、ファイルではなくサブフォルダを数えたいときは、「/d」オプションを付けて次のようにしてください。
for /d %%i in (*) do (set /a Total+=1)
処理を行う方の「for」にも同様に「/d」オプションを付ければ、サブフォルダに対して処理を行うバッチになります。
rem ----------Totalのチェック----------
if %Total% lss 20 (
set /a PreBar=20 - %Total%
for /l %%i in (1,1,!PreBar!) do (set /p Bar=■< nul)
)
「Total」のチェックは、20未満の対応のみで大丈夫です。バーの不足分を埋めています。
if not %%i == %~nx0 (
rem ==========処理内容(%%iに入った各ファイルに対する処理)==========
)
処理内容にもよりますが、自身のバッチファイルを除くif分岐を入れています。「%~nx0」で自身のバッチの「ファイル名+拡張子」が得られますので、それと異なる場合のみ処理を実行します。
プログレスバーは、いかに「set /p Bar=■< nul」をループに組み込むかを考えればできると思います。
「■」は全角文字ですが、半角の「*」や「-」等でも表現可能です。半角を使う場合は罫線を短くし、「Total」のチェックと「Rate」の計算の部分を変更すれば実装できます。
4 thoughts on “バッチ処理でプログレスバーを表示する方法”
完成度すごい高いですね
ありがとうございます! そう言ってもらえると嬉しいです☆
基本ロジック頂きました。
これで処理途中で心配になって中断操作するような輩がいなくなるでしょうw
ありがとうございます。
コマンドプロンプトでカーソルが点滅しているだけだと、動いているのか心配になる人はいると思うんですよね。
少しでもお役に立てる部分があったら嬉しいです。コメントありがとうございます☆