コマンドプロンプトでプログレスバーを再現


概要

batとかで処理をすると、裏で動いているのか死んでいるのかわからなくなるときがあって不親切かなと、、、
あとユーザの気持ちになると、プログレスバーがあった方がPCが仕事している事を認識できるので
待ち時間のイライラがちょっと緩和される気がしました。

現物

進捗を記録していくテキストファイルを監視し、そのテキストファイルの最終行が書き換わるごとにプログレスバーを表示します。
「Done」という文字列を認識すると終了します。

仕組み

プログレスバー本体のバッチファイルやSLEEPについて。

ファイル構造

ぶっちゃけProgressBar.batが進捗管理用のテキストファイルを開けて、sleep.exeがどっか見える所にあればいいです。
下は一例です。

OneDrive tool.zip

c:\tool>tree /F
Folder PATH listing for volume Windows7_OS
Volume serial number is 2E48-0DB5
C:.
│   progress.txt
│
├───ProgressBar
│       ProgressBar.bat
│       ReadMe.txt
│
└───Sleep
        ReadMe.txt
        sleep.exe

スクリプト

プログレスバーのbatファイルは下記です。

ProgressBar.bat
@echo off

rem 進捗用テキストファイルを%temp%に吐き出すようにして、V_FILEPATHの値を%temp%\%1にすると絶対パスで渡せるためお勧め。
set V_FILEPATH=%1
set V_FL=""
set V_RUNSCRIPT=""
set V_TOOLPATH=""
set V_SLEEPPATH=""
set V_CURRENTDIRECTORY=%cd%

rem 実行パスからsleepパス取得
cd /d %~dp0
cd ../
set V_TOOLPATH=%cd%

rem sleep.exeパス取得
set V_SLEEPPATH=%V_TOOLPATH%\Sleep\sleep.exe
if not exist %V_SLEEPPATH% call :ERR "sleep.exe is not exist"

rem カレントディレクトリへ移動
cd %V_CURRENTDIRECTORY%

rem プログレスバー処理開始
:LOOP
    call :TAIL %1%
    set RUNSCRIPT=%V_FL%
    set /p script="%RUNSCRIPT% | "< nul
    :PROGRESS
        set /p x="#"< nul
        rem ping 1.0.0.0 -w 500 -n 1 > nul
        rem timeout /t 1 > nul
        call %V_SLEEPPATH% -m 500

        call :TAIL %1%
        if %RUNSCRIPT% neq %V_FL% goto :LOOPCONTINUE
        if "%V_FL%" == "Done" goto :DONE
    goto :PROGRESS

:LOOPCONTINUE
    echo.
    if "%V_FL%" == "Done" goto :DONE
goto :LOOP


rem サブルーチン:テキストファイル最終行取得 グローバル変数V_FL
:TAIL

for /F "TOKENS=1" %%s in (%V_FILEPATH%) do set V_FL=%%s

exit /b


rem 終了
:DONE

echo.
echo Done.
pause

exit 0


rem エラー
:ERR

cd /d %V_CURRENTDIRECTORY%
echo ERR %~1
pause

exit 0

使い方

gifアニメの通り、ProgressBar.batの引数に進捗を最終行に吐き出すテキストファイルのパスを渡して起動。

進捗を記録するテキストファイルを用意しておいて、処理開始毎に最終行へ今の処理内容を書き込むような事をすればそれっぽく動けます。
bat, vbsだと下記のような感じ。

bat
echo "実行中の処理~" >> progress.txt
vbs
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objFile = objFso.OpenTextFile("c:\tool\progress.txt", 8, True)

If Err.Number > 0 Then
    WScript.Echo "Open Error"
Else
    objFile.WriteLine & "実行中の処理~"
End If

objFile.Close
Set objFile = Nothing
Set objFso = Nothing

SLEEP.EXE

sleep.exeはWindows Server 2003 Resource Kit Toolsというものを使用しました。
ミリ秒指定でスリープするためだけのexeです。
(exeのインストーラですが7zipやWinRARなら中身を抜き出す事ができます)

スクリプトによくあるping飛ばした時の待機時間を利用したコードもあるのですが、そもそもネット環境が無いようなところだと使えないので、ちゃんとスリープするならこれを使用したほうが良さそうです。