Search code examples
for-loopbatch-filecmdecho

Progress Bar Dos


I'm new to dos 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%
)

Solution

  • 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