バッチ処理でプログレスバーを表示する方法

時間がかかるバッチ処理をするときに、コマンドプロンプトの画面にプログレスバー(進捗状況)を表示する方法です。

処理する総数を指定、もしくは取得して、処理が完了した割合に応じてバーを表示します。


目次

  1. バーを表示する方法
  2. 回数を指定して処理を行うバッチの例
  3. フォルダ内の各ファイルに対して処理を行うバッチの例

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」の計算の部分を変更すれば実装できます。


Leave a comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

6 + two =

4 thoughts on “バッチ処理でプログレスバーを表示する方法”