Coding a real time progress bar in batch
batch-file
Solution
Just a skelleton. Adapt as needed.
The basic idea is to output the line with the progress bar with an ending carriage return to return to the start of the line and be able to repaint the next state over the previous one.
All "problematic" code wrapped into subroutines so you only need to `call :drawProgressBar percentValue "operationText"`
@echo off
setlocal enableextensions disabledelayedexpansion
for /l %%f in (0 1 100) do (
call :drawProgressBar %%f "up test with a long text that will not fit on screen unless you have a lot of space"
)
for /l %%f in (100 -1 0) do (
call :drawProgressBar %%f "going down test"
)
for /l %%f in (0 5 100) do (
call :drawProgressBar !random! "random test"
)
rem Clean all after use
call :finalizeProgressBar 1
call :initProgressBar "|" " "
call :drawProgressBar 0 "this is a custom progress bar"
for /l %%f in (0 1 100) do (
call :drawProgressBar %%f
)
endlocal
exit /b
:drawProgressBar value [text]
if "%~1"=="" goto :eof
if not defined pb.barArea call :initProgressBar
setlocal enableextensions enabledelayedexpansion
set /a "pb.value=%~1 %% 101", "pb.filled=pb.value*pb.barArea/100", "pb.dotted=pb.barArea-pb.filled", "pb.pct=1000+pb.value"
set "pb.pct=%pb.pct:~-3%"
if "%~2"=="" ( set "pb.text=" ) else (
set "pb.text=%~2%pb.back%"
set "pb.text=!pb.text:~0,%pb.textArea%!"
)
<nul set /p "pb.prompt=[!pb.fill:~0,%pb.filled%!!pb.dots:~0,%pb.dotted%!][ %pb.pct% ] %pb.text%!pb.cr!"
endlocal
goto :eof
:initProgressBar [fillChar] [dotChar]
if defined pb.cr call :finalizeProgressBar
for /f %%a in ('copy "%~f0" nul /z') do set "pb.cr=%%a"
if "%~1"=="" ( set "pb.fillChar=#" ) else ( set "pb.fillChar=%~1" )
if "%~2"=="" ( set "pb.dotChar=." ) else ( set "pb.dotChar=%~2" )
set "pb.console.columns="
for /f "tokens=2 skip=4" %%f in ('mode con') do if not defined pb.console.columns set "pb.console.columns=%%f"
set /a "pb.barArea=pb.console.columns/2-2", "pb.textArea=pb.barArea-9"
set "pb.fill="
setlocal enableextensions enabledelayedexpansion
for /l %%p in (1 1 %pb.barArea%) do set "pb.fill=!pb.fill!%pb.fillChar%"
set "pb.fill=!pb.fill:~0,%pb.barArea%!"
set "pb.dots=!pb.fill:%pb.fillChar%=%pb.dotChar%!"
set "pb.back=!pb.fill:~0,%pb.textArea%!
set "pb.back=!pb.back:%pb.fillChar%= !"
endlocal & set "pb.fill=%pb.fill%" & set "pb.dots=%pb.dots%" & set "pb.back=%pb.back%"
goto :eof
:finalizeProgressBar [erase]
if defined pb.cr (
if not "%~1"=="" (
setlocal enabledelayedexpansion
set "pb.back="
for /l %%p in (1 1 %pb.console.columns%) do set "pb.back=!pb.back! "
<nul set /p "pb.prompt=!pb.cr!!pb.back:~1!!pb.cr!"
endlocal
)
)
for /f "tokens=1 delims==" %%v in ('set pb.') do set "%%v="
goto :eof
Problem
I want to use a real time progress bar where it updates as code is written or installing something or loading a file. Example: ``` @echo off :main echo Updating file... [PROGRESS BAR HERE] ``` The "PROGRESS BAR HERE" indicates the part that I want the real time progress bar to be placed at.