uib
uib

Reputation: 33

Windows cmd: echo without new line but with CR

I would like to write on the same line inside a loop in a windows batch file. For example:

setlocal EnableDelayedExpansion
set file_number=0
for %%f in (*) do (
  set /a file_number+=1
  echo working on file number !file_number!
  something.exe %%f
)
setlocal DisableDelayedExpansion

This will result in:

echo working on file number 1

echo working on file number 2

echo working on file number 3

. . .

I would like all of them to be on the same line. I found a hack to remove the new line (e.g. here: Windows batch: echo without new line), but this will produce one long line.

Thanks!

Upvotes: 3

Views: 12223

Answers (4)

Helal Rajeh
Helal Rajeh

Reputation: 1

@echo off
setlocal enableextensions enabledelayedexpansion

Rem Get a carriage return character
set "CR=" & for /f %%a in ('copy /Z "%~f0" nul') do if not defined CR set "CR=%%a"
rem The progress bar
set "fill=[###################]"


echo(
rem For each character in the fill
for /l %%a in (2 3 21) do (
    rem Calculate the right part of the bar
    set "spaces=!fill:~%%a!"

    rem Output the left and right parts of the bar and carriage return
    <nul set/p ".=:: Please Connect Device : !fill:~0,%%a!!spaces:#= !!CR!"

    rem Pause for a second
    ping -n 2 "" > nul
)
echo(

Upvotes: 0

Radoslaw
Radoslaw

Reputation: 1

The above no longer works in Windows 7 and later. I found the reason is delayed expansion that should be set after ASCII_13 assignment, maybe someone smart could explain why exactly.

Anyway, the code below works both on Windows 7 and Windows 10.

@set licz=0
@setlocal
@for /f %%a in ('copy /Z "%~dpf0" nul') do @set "ASCII_13=%%a"
@setlocal enabledelayedexpansion
:loop
@set /a licz=licz+1
@set /p "=Waiting time: %licz% seconds!ASCII_13!" <NUL
@Timeout /T 1 /Nobreak > NUL
@GOTO loop

If you do not like the cursor blinking at beginning of the line, transfer ASCII_13 to the beginning to execute CR before text. Needs to be preceeded by any ASCII character, though, to avoid getting stripped. And this will be visible as the last char on the line, so be wary here :)

@set /p "=.!ASCII_13!Waiting time: %licz% seconds" <NUL

Upvotes: 0

pollaris
pollaris

Reputation: 1321

Thanks to the answer of MC ND I have a created a subroutine, echocr, that you can call without delayed expansion, that will echo a string with only a carriage return, and no newline. (The spaces after %input% are adjusted to cover all previous messages).

You can use it to overwrite a line as shown in the modified code:

@echo off

call :echocr "good morning"
PING -n 2 127.0.0.1>nul
call :echocr "good afternoon"
PING -n 2 127.0.0.1>nul
call :echocr "bye now"
PING -n 2 127.0.0.1>nul
pause

:echocr

:: (echo string with carriage return, no line feed)

for /F "tokens=1 delims=# " %%a in (
'"prompt #$H# & echo on & for %%b in (1) do rem"'
) do set "backspace=%%a"

set input=%~1
set "spaces40=                                       "
set "spaces120=%spaces40%%spaces40%%spaces40%
for /f %%a in ('copy "%~f0" nul /z') do (  
    set /p ".=*%backspace%%spaces120%%%a" <nul      
    set /p ".=*%backspace%%input%%%a" <nul
)    
exit /b

Upvotes: 1

MC ND
MC ND

Reputation: 70923

@echo off
    setlocal enableextensions enabledelayedexpansion

    for /f %%a in ('copy "%~f0" nul /z') do set "CR=%%a"

    set "count=0"
    for %%a in (*) do (
        set /a "count+=1"
        <nul set /p ".=working on file !count! !CR!"
    )

The first for command executes a copy operation that leaves a carriage return character inside the variable.

Now, in the file loop, each line is echoed using a <nul set /p that will output the prompt string without a line feed and without waiting for the input (we are reading from nul). But inside the data echoed, we include the carriage return previously obtained.

BUT for it to work, the CR variable needs to be echoed with delayed expansion. Otherwise it will not work.

If for some reason you need to disable delayed expansion, this can be done without the CR variable using the for command replaceable parameter

@echo off
    setlocal enableextensions disabledelayedexpansion

    for /f %%a in ('copy "%~f0" nul /z') do (
        for /l %%b in (0 1 1000) do (
            <nul set /p ".=This is the line %%b%%a"
        )
    )

Upvotes: 6

Related Questions