Joseph
Joseph

Reputation: 7785

How to display a progress bar with a Windows batch file?

I'm new to Windows batch commands and I want to achieve the progress bar like in the picture.
First you have to initialize the process value and the calculate the percentage of it and you have to display it using the progress bar.

You can do Alt+219 and Alt+176 for progress bar

Here's what i have done so far.

echo off
cls
SetLocal EnableDelayedExpansion
set processValueString=200
set a/ processValue=200
set a/ percentage=0

echo Process value: %processValueString%

for /l %%a in (1,1, %processValue%) do (
    set a/ percentage = %%a / %processValue% * 100
    echo Percent: !percentage! %
    echo Processing: !a! / %processValue%
)

Upvotes: 2

Views: 9517

Answers (4)

ScriptKidd
ScriptKidd

Reputation: 851

ANSI sequences were added as a part of the Redstone Update, so it will only work from Windows 10+


Use a combination of ANSI sequences and the ability of FORFILES to print ASCII characters

@echo off
^
%=-----------DO NOT REMOVE THIS LINE-----------=%
Y
%= Y to abort when Ctrl-C is pressed =%
%= N to ignore =%
SETLOCAL EnableDelayedExpansion

::Defaults
( set LF=^
%=-----------DO NOT REMOVE THIS LINE-----------=%
)
FOR /F %%C in ('copy /Z "%~f0" nul') do set "CR=%%C"
FOR /F %%E in ('prompt $E ^& ^<nul cmd /k') do set "ESC=%%E"

::SETTINGS
color a
>nul chcp 65001
mode CON: COLS=120 LINES=31

::INITIALIZE
call :init 0xDB] 0xB0 40 200 

echo Starting at %time%
<nul set/p=[
>nul 2>nul call :progessBar
echo Finished at %time%

exit /b


:init bar tbd length processvalue
::Custom parameters defined by user
set "bar=%~1"
set "tbd=%~2"
set /a "barlength=%~3"
set /a "processvalue=%~4" 

::Default values
if NOT DEFINED bar set "bar=0xDB"
if NOT DEFINED tbd set "tbd=0xB0"

::Set bar & tbd
>hex.tmp <hex.tmp (
FOR %%V in (bar tbd) do (
FORFILES /P "%~dp0." /M "%~nx0" /C "cmd /c echo(!%%V!"
set/p"%%V=" CLEAR VARIABLE
set/p"%%V=" SET VARIABLE
))

del hex.tmp
exit /b


:main
>&3 (
  echo(
  for /L %%N in (0 1 %barlength%) do echo(!LF!%ESC%[2A%ESC%[%%NC%tbd%
  for /L %%N in (0 1 %processvalue%) do (
    set/ashowBar=%%N*barlength/processvalue,percentage=%%N*100/processvalue
    echo(Percent: !percentage!%%!LF!Processing: %%N / %processvalue%!LF!%ESC%[3A%ESC%[!showBar!C%bar%
  )
  echo(!LF!
)
exit /b


:progessBar
<"%~f0" call :main

Sources:


Edit: This answer is limited to 1 bar/second, but is compatible across all versions of windows from 7. (On some the /NOBREAK switch is unsupported.)

At DosTips, @Aacini discovered TIMEOUT redirected to CON brings the cursor home! @jeb also showed that the output can be eliminated via piping | (normally TIMEOUT does not support piping, so SET /P is used.) However, it is (nearly) impossible to remove the countdown at the top.

@echo off
====SETLOCAL EnableDelayedExpansion EnableExtensions
cls


::SETTINGS
color a
>nul "%__APPDIR__%CHCP.COM" 65001
"%__APPDIR__%MODE.COM" CON: COLS=120 LINES=31


::INITIALIZE
::Custom parameters defined by user
set "bar_ASCII=0xDB"
set "tbd_ASCII=0xB0"
set/a"#len=40,#totalValue=200,#newlines=1" %====# of newlines to echo before progressBar, >0====%

::DEFAULTS
set "overwrite=x"
FOR /L %%# in (1,1,6) do set "overwrite=!overwrite!!overwrite!"
%= CLEAR VARIABLES =%
set "loaded="
set "remain="
set "progressBar="


::Set LOADED & REMAIN
>hex.tmp <hex.tmp (
    "%__APPDIR__%FORFILES.EXE" /P "%~dp0." /M "%~nx0" /C "cmd /c echo(!bar_ASCII!!tbd_ASCII!"
    set/p"=" SKIP empty line
    set/p"_=" GET 2nd line
)
del hex.tmp
set "loaded=!_:~0,1!"
set "remain=!_:~1!"


::Set $NEWLINES
FOR /L %%L in (2,1,%#newlines%) do set ^"$newlines=!$newlines!^
%====DO NOT REMOVE ME====%
"
echo(
for /L %%N in (0,1,%#len%) do set "progressBar=!progressBar!!loaded!"
for /L %%N in (0,1,%#totalValue%) do (
    set/a"percentage=%%N*100/#totalValue"
    echo(!$newlines!
    echo(Percent: !percentage!%%
    echo(Processing: %%N / %#totalValue%
    echo(!progressBar:~0,%%N!
    >con "%__APPDIR__%TIMEOUT.EXE" /t 1 /nobreak %====Time delay in SECONDS, do not set to 0====%|"%ComSpec%"/Q /C "FOR /F %%C in ('copy /Z "%~f0" nul') do set/p"=_%%C%overwrite%""
)


====ENDLOCAL
exit /b

Upvotes: 2

Ale865
Ale865

Reputation: 126

If you want , you can print ascii codes easily with this application :

download url :

https://mega.nz/file/2AZA3Y5T#y8z1aIKJHPiHmnlkgv-dYmn0J2fozz83uGdXS7umyLE

There are also a lot of characters for progress bars.


the syntax is simple :

char [ascii code] [ascii code]

For example:

char 186 186 201 186

You can also add empty characters :

char 186 " " 186

I hope it helps

Upvotes: 1

Aacini
Aacini

Reputation: 67256

This works here (very fast!):

EDIT: Code modified for "bar with variable steps"

@echo off
SetLocal EnableDelayedExpansion

rem Define the "amounts" of each one of the (7) steps that comprise this job
set "amounts= 10 6 2 9 3 7 4"
set width=60

set "off="
set "on="
for /F "tokens=1,2" %%X in ('FORFILES /M "%~nx0" /C "cmd /c echo 0xDB 0xB0"') do (
   for /L %%i in (1,1,%width%) do set "on=!on!%%X" & set "off=!off!%%Y"
)

rem Get CR, BS and TAB ASCII control characters:
for /F %%a in ('copy /Z "%~f0" nul') do set "CR=%%a"
for /F %%a in ('echo prompt $H ^| cmd') do set "BS=%%a"
set "TAB="
rem First, try the method for Windows XP
for /F "skip=4 delims=pR tokens=2" %%a in ('reg query hkcu\environment /v temp' ) do set "TAB=%%a"
rem Then, the method for newer versions
rem http://www.dostips.com/forum/viewtopic.php?f=3&t=1733&p=6840#p6853
for /F "tokens=2 delims=0" %%a in ('shutdown /? ^| findstr /BC:E') do if not defined TAB set "TAB=%%a"
rem String to go up one line in SET /P command
set "LineUp=%TAB%!BS!!BS!!CR!"

cls
echo Percentage of values processed
echo/
echo %TAB%%off%
echo %TAB%Percent: 0%%
echo %TAB%Processing: 0/%processValue%

set /A "processValue=0, summa=0"
for %%a in (%amounts%) do set /A processValue+=%%a
for %%N in (%amounts%) do (
   set /A "summa+=%%N, Percent=summa*100/processValue, PercentOn=Percent*width/100
   for %%i in (1,1,4) do set /P "=.!LineUp!" < nul
   for %%p in (!PercentOn!) do echo %TAB%!on:~0,%%p!
   echo %TAB%Percent: !Percent!%%
   echo %TAB%Processing: !summa!/%processValue% (current: %%N^)  

   timeout /T %%N > nul

)

enter image description here

For details on the method to "go up one line", see Move cursor to any position using just ECHO command

NOTE: The method to move cursor up one line works in all Windows versions excepting Windows 10 using the new console. You need to enable "Legacy mode" in the cmd.exe window console in order for this method to work...

Upvotes: 2

Stephan
Stephan

Reputation: 56228

With some minor changes to HackingAddict1337's code, it's possible to have a fixed (choosable) total length of the bar:

@echo off
cls
SETLOCAL EnableDelayedExpansion

set /a "processValue=200"
set "bar=0xDB" Character used by progress bar (SUPPORTS HEX)
set "tbd=0xB0"
set "barLength=40"
( set LF=^
%=-----------DO NOT REMOVE THIS LINE. the LF variable is for future use in a function, it's currently useless-----------=%
)
FOR /F %%B in ('FORFILES /P "%~dp0." /M "%~nx0" /C "cmd /c echo(!bar!"') do set "bar=%%B"
FOR /F %%B in ('FORFILES /P "%~dp0." /M "%~nx0" /C "cmd /c echo(!tbd!"') do set "tbd=%%B"
FOR /F %%B in ('copy /Z "%~f0" nul') do set "CR=%%B"
FOR /F %%B in ('prompt $E ^& ^<nul cmd /k') do set "ESC=%%B"
for /l %%N in (0,1,%barLength%) do set "emptybar=!emptybar! "

echo Starting at %time%!LF!
for /l %%N in (0 1 !barLength!) do echo(!LF!%ESC%[2A%ESC%[%%NC%tbd%
for /L %%N in (0 1 %processValue%) do (
  set /a showBar=%%N*barLength/processValue
  set /a percentage=%%N*100/processValue
  echo(Processing: %%N / %processValue% = !percentage!%%!LF!%ESC%[2A%ESC%[!showBar!C%bar%
  ping -4 -n 1 127.0.0.1 >nul 
)
echo !LF!Finished at %time%
pause>nul
ENDLOCAL

(adapted to HackingAddicts faster code)

Joseph's concerns:

  1. You lack the looks of the "measurement bar", this should look like the ALT+176, this is I think this code "echo [%emptybar%]".
    adapted to look as you want it:

  2. Another thing you lack is very simple just the percentage, ex: Percentage: 10%.
    also adapted:

Starting at 15:58:44,10
 ██████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
Processing: 32 / 200 = 16%
  1. The speed of progress bar stick is variable which means the speed per step is not constant.
    that's because of rounding. Nothing we can do about it, except we make processValue equal to barLength or an integer multiple.

Upvotes: 1

Related Questions