Batch Files

Cursor Positioning

Introduction

This page was written because in June 2025, Reddit user Own_Western8448 asked about inserting a 'rotating line' timer in a batch file to indicate the script is running.

To make the script work, the cursor has to write the characters / - \ | in order and at the same position on the screen.

Moving the cursor relies on the use of the ANSI (American National Standards Institute) ASCII (American Standard Code for Information Interchange) control codes.


ANSI ASCII Control Codes

The American Standards Association (ASA), now the American National Standards Institute (ANSI), began work on the American Standard Code for Information Interchange (ASCII) in October 1960. The encoding scheme had origins in the 5-bit telegraph codes invented by Émile Baudot in 1870, but there were other 5-bit and 6-bit character encodings in use. To try and standardize these sets, they chose a 7-bit encoding system, mainly to help keep down on the cost of data transmission but 7-bit confined ASCII to 128 characters.

The first 32 ASCII characters (0 - 31) and the last one (127), were reserved for control codes for printers, teleprinters, and other devices which allowed for just 95 printable characters, and so of course, English was the language used for these. The first version of ASCII was introduced in 1963 and a revised version in 1967, with the last revision being in 1986.

In the 1970s ANSI introduced a set of control codes for terminal displays and keyboards. The control codes codes can control the text and background colours of the screen, the cursor position and even the screen mode which controlled the number of columns seen on the screen.

The original MS DOS was introduced in August 1981 and did not include ANSI support. MD DOS v2 was released in March 1983, that and all future editions of it, included the ansi.sys device driver that could use the ANSI terminal control codes. Ansi.sys was not loaded by default but could easily be loaded by editing the config.sys file.

No version of Windows natively supported the ANSI codes until the Windows 10 version 1511 update of November 2015 and is enabled by default.


Cursor Control Codes

The cursor and related control codes are:

ESC Code Sequence Description
ESC[H Moves cursor to home position (0, 0)
ESC[{line};{column}H
ESC[{line};{column}f
Moves cursor to line #, column #
ESC[#A Moves cursor up # lines
ESC[#B Moves cursor down # lines
ESC[#C Moves cursor right # columns
ESC[#D Moves cursor left # columns
ESC[#E Moves cursor to beginning of next line, # lines down
ESC[#F Moves cursor to beginning of previous line, # lines up
ESC[#G Moves cursor to column #
ESC[6n Request cursor position (reports as ESC[#;#R)
ESC M Moves cursor one line up, scrolling if needed
ESC 7 or ESC[s Save cursor position
ESC 8 or ESC[u
Restores the cursor to the last saved position
ESC[J Erase in display (same as ESC[0J)
ESC[0J Erase from cursor until end of screen
ESC[1J Erase from cursor to beginning of screen
ESC[2J Erase entire screen
ESC[3J Erase saved lines
ESC[K Erase in line (same as ESC[0K)
ESC[0K Erase from cursor to end of line
ESC[1K Erase start of line to the cursor
ESC[2K Erase the entire line

Inserting the Escape Characters

Sites such as Computer Help, and Wikipedia have descriptons and tables showing what the escape codes do but are not very good at describing how to insert these commands into the command line or batch files. Sites such as the wonderful Rob van der Woude's do better.

The COLOR command can change the entire text and background colours of the screen; the ANSI control codes change the text and background colours of indvidual portions or lines of text, move the cursor around and a couple of more specialized functions.

In order to use these control squences the terminal has to be instructed that what follows is actually a control squence and is not normal text. This is what the ESCAPE seuences do. After a little trial and error this is what I found:

Command Prompt

The ANSI control codes can be used at the command prompt but they must be echo'd to the screen. To produce the control code use Ctrl + [

To change the text colour to yellow the following command can be used:

echo Ctrl + [[33m

To use multiple escape commands, separate them with a semicolon. To produce "Warning! Warning! Warning!" with blinking bold yellow text on a red background use:

echo Ctrl + [[1;33;41;5m Warning! Warning! Warning! Ctrl + [[m

Notice the double [[ characters, one produced while pressing the Ctrl key and one without. The final [[m sequence is to turn the control codes off and return to normal text. It is the same as Ctrl + [[0m

The ECHO command has to be used otherwise a warning will be produced saying:

[Character] is is not recognized as an internal or external command, operable program or batch file.

This error message can not be suppressed by redirecting the standard output to null using >NULL or redirecting the error messages to null using 2>NULL. The error message will show and the control code may not work at all.

Batch Files

When testing these scripts, or developing your own, it is important to remember to close the command prompt and start a new one. This is because sometimes results of a script interact with the previous and what you may think is working, is actually not.

Method 1 - Using Ctrl + [

The control eccape characters can be sent from the command prompt to a batch file using a redirect:

echo Ctrl + [ > myfile.bat

The myfile.bat file will then contain a representation of the command character, or a character showing the actual character cannot be found such as ⍰. The rest of the line can then be completed as normal

An entire command line, including the echo can be sent to the file using the same technique using:

echo echo Ctrl + [[1;33;41;5m Warning! Warning! Warning! Ctrl + [[m

Again, notice the two [ characers in the line and the two echo commands. The first echo suppresses the warning message, and the second echo is sent to the myfile.bat file as text. The myfile.bat file now contains:

echo ⍰[1;33;41;5m Warning! Warning! Warning! ⍰[m

The control character inserted into the file can be copied to a different part of the batch file or even copied to a new file and still work as intended. The >> (redirect and append) command can also still be used to add lines to a file.

Method 2 - Using Ctrl + [ and SET

This method is similar to Method 1 to start, but assigns the control squence to a variable that can be reused in the batch file. At a command prompt type:

echo set "ESC=Ctrl + [" > myfile.bat

myfile.bat now contains the line:

set "ESC=⍰"

The %ESC% variable can now be used from inside the batch file to insert the command escape sequence. Using the sequence I have used before, a batch file can now be written as:

@echo off
set "ESC=⍰"
echo %ESC%[1;33;41;5m Warning! Warning! Warning!
echo %ESC%[m

Method 3a - Using For, Prompt and Set

In a batch file type:

@echo off
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do set ESC=%%b
echo %ESC%[1;33;41;5m Warning! Warning! Warning!
echo %ESC%[0m

Method 3b - Using For, Prompt and Set (Simplified)

In a batch file type:

@echo off
for /F %%a in ('echo prompt $E ^| cmd') do set "ESC=%%a"
echo %ESC%[1;33;41;5m Warning! Warning! Warning!
echo %ESC%[0m

These methods work because of the switches that can be used with the prompt command. $H is a backspace and $E is the ANSI escape code (code 27). This code is captured and placed in the ESC variable.

Advantages of these methods are that no interaction is required with the command prompt to write the batch file and the command escape sequence is saved to a variable.

Method 4 - Using Forfiles

In a batch file type:

FORFILES.EXE /P %~dps0 /M %~nxs0 /C "CMD.EXE /C ECHO 0x1B[1;33;41;5m Warning! Warning! Warning!0x1B[0m

This method does not require any interaction with the command prompt and works because forfiles interprets hexadecimal characters (0xdd format) from the command line. To ensure it works just once, the /P (path) parameter is set to the folder the batch file is in using %~dps0 and the /M (search mask matching) parameter is set to the batch file's name and extension using %~nxs0.

Unfortunately, I do not know how to save 0x1B to a variable, so the entire line has to be repeated to change the command escape sequence.


Some Batch Files

Here's a simple batch file:

@echo off
echo This is line 1
echo This is line 2
echo This is line 3
set count=5
:Count
echo %count%
Timeout /t 1 /nobreak > null
set /a count=count-1
if %count% EQU 0 goto Next
goto Count
:Next
echo This is the end of the batch file

The output of the above script is:

Batch file 1 output

The newline produced at the end of the echo command can be suppressed by piping it to a variable as in the following batch file:

@echo off
echo This is line 1
echo This is line 2
echo This is line 3
set count=5
:Count
if %count% EQU 5 echo | set /p dummyName="%count%"
if %count% LSS 5 echo | set /p dummyName=", %count%"
Timeout /t 1 /nobreak > null
set /a count=count-1
if %count% EQU 0 goto Next
goto Count
:Next
echo.
echo This is the end of the batch file

The output of the above script is:

Batch file 2 output

The next batch file actually used the ANSI codes to move the cursor to produce an interesting effect. The code fot the script is:

@echo off
echo This is line 1
echo This is line 2
echo This is line 3
set count=5
:Count
echo %count%..
Timeout /t 1 /nobreak > null
set /a count=count-1
echo ⍰[2A
if %count% EQU 0 goto Next
goto Count
:Next
echo This is the end of the batch file

The line ⍰[2A was appended to the batch file by using the command line:

echo echo Ctrl [[2A >> move-cursor.bat

The line was then copy and pasted into its correct position. What it does is move the cursor up two lines ready to print %count%..

The final output of the script is:

Batch file 3 output

But before it reaches this final form the final line in the final output that say's "This is the end of the batch file" shows the values of %count%.., ie 5.. then 4.. then 3.. then 2.. then 1.. before finally showing the text and finishing, as in the following video:

The video was recorded using OBS Studio and as it only required simple editing, edited with a 2012 version of Windows Movie Maker.


Sources and Resources

Add Progress Spinner To Menu Batch File (Computer Hope)
ANSI escape code (Wikipedia)
ANSI Escape Sequences (GitHub)
ANSI sequences (Rob van der Woude's Scripting Pages)
Echo (Microsoft Learn)
Echo (SS64)
How to code a spinner for waiting processes in a Batch file? (Stack Overflow)
If (Microsoft Learn) - includes a section on comparison operators
If (SS64) - includes a section on comparison operators
Indicative timer (Reddit) - the post that inspired this page
MS-DOS and Windows command line ansi.sys command (Computer Hope)
Progress indicator in a batch file while tracert runs (Super User)
Timeout (Microsoft Learn)
TIMEOUT.exe (SS64)
Windows batch: echo without new line (Stack Overflow)