1.

Solve : Echo repeatedly in same place without 3rd party exe?

Answer»

No need for GNU echo or other 3rd party apps.

Code: [Select]echo off
REM You need this
setlocal EnableDelayedExpansion

REM How to print over and over again on the same line

REM      This is a trick to get an ASCII 13 character
REM      (CR - Carriage Return) into a variable
for /F %%a in ('copy /Z "%0" nul') DO set "CR=%%a"

REM This is a demo that repeatedly echoes the time in the same place
REM Stop with CTRL + C
:loop

  REM <nul set /p "=xxx yyy zzz" is a trick to print xxx yyy zzz without a new line
  REM and echoing !CR! returns the cursor to the start of the line
  REM Must use the ! delayed expansion format for !CR!
  <nul set /p "=The time now is is %time%!CR!"

  REM make a delay
  ping -n 1 127.0.0.1 > nul

goto loop

It didn't perform in XP, the output was displayed as one continuous line indicating that both CR and LF were suppressed.  Any words of wisdom?

This worked, a tad slow probably due to the Cls repeats but gets there.  Same Ctrl+C to exit:

Code: [Select]echo off

:loop
  cls
 
  <nul set /p ="The time now is %time%"

  ping -n 1 127.0.0.1 > nul

goto loop


Quote from: Dusty on December 01, 2011, 07:26:59 PM

It didn't perform in XP, the output was displayed as one continuous line indicating that both CR and LF were suppressed.  Any words of wisdom?

This worked, a tad slow probably due to the Cls repeats but gets there.  Same Ctrl+C to exit:

Code: [Select]echo off

:loop
  cls
 
  <nul set /p ="The time now is %time%"

  ping -n 1 127.0.0.1 > nul

goto loop


I have run the same code that I posted above, in Windows 7 (64 bit) and Windows XP SP3 (32 bit) and it works equally well in both. Are you running exactly the same code? (That is, did you re type it or copy-and-paste?)


Quote from: Salmon Trout on December 02, 2011, 12:09:36 AM
I have run the same code that I posted above, in Windows 7 (64 bit) and Windows XP SP3 (32 bit) and it works equally well in both.

... and Windows 2000 SP4 also.




Right, thanks for all your work.   The script was copied/pasted.   I was probably a bit too hasty in completely condemning the script but still have a problem.

Although I've only tested in XP Home and XP Pro Corporate I cannot get the script to run successfully if Cmd.exe is opened then the bat filename entered using Start>Run>Cmd or opening a Cmd window using a shortcut..  This is true regardless of where the script is located.

The result is:

Code: [Select]The time now is is 17:33:53.56TheThe time now is is 17:33:53.73TheThe time now is is 17:33:53.90TheThe time now is is 17:33:54.06TheThe time now is is 17:33:54.25TheThe time now is is 17:33:54.40TheThe time now is is 17:33:54.57TheThe time now is is 17:33:54.75TheThe time now is is 17:33:54.92TheThe time now is is 17:33:55.09TheThe time now is is 17:33:55.25TheThe time now is is 17:33:55.43TheThe time now is is 17:33:55.59TheThe time now is is 17:33:55.78TheThe time now is is 17:33:55.95TheThe time now is is 17:33:56.09TheThe time now is is 17:33:56.28TheThe time now is is 17:33:56.42TheThe time now is is 17:33:56.60TheThe time now is is 17:33:56.78TheThe time now is is 17:33:56.93TheTerminate batch job (Y/N)?
Note the STUTTERING "The"

A wee bit of sleuthing shows that CR is being set to The in the first loop.

However the script does run successfully if run in the GUI (by clicking to open the file).   Any pearls of wisdom as to what I'm doing wrong?

Are you gonna believe it?    I was invoking the batch script using only the filename (without extension) so %0 contained just Trial1

When I invoked the script using Trial1.bat all went smoothly.   Another lesson learned.

Thanks again S.T.

D.I am gonna believe it, because of my own mistake! I saw the "trick to get a carriage return into a variable" ages ago and saved the line to play around with sometime. In the original code, it wasn't %0 - it was %~dpnx0 which expands to the full drive letter, path, name and extension of the script being run. I thought I'd simplify it and it worked OK for me because I always called it either in a command session using the name + extension or from Windows Explorer by double clicking the script icon. From what I can see, the trick exploits the fact that COPY /Z generates a CR for FOR /F to capture after a successful operation, (copying the current script to the null device must always work), and %0 works if you specify the extension, %~nx0 works if you are calling it from a different folder on the same drive, and you need %~dpnx0 if you are calling it from a different drive. I GUESS this makes sense in terms of how the shell assumes the current drive, path, etc when commands are typed, and knowing that Windows Explorer uses the whole drive/path/name/extension. So that %~dpnx0 was there for a reason, and you have very kindly helped me get that straight in my head, by your alertness and patient testing, for which I thank you.
Gee whizz, my ego has just done a quantum leap forward.

I've also found that if any accessible filename is USED instead of of %0 the script is quite happy to proceed when invoked using only the filename, obviously the file must be a permanent fixture in its location.   I have had success using %comspec%.

Onward and upward, thank you for the very interesting explanation.



I have found another way to get an ASCII 13 (or any other) character into a batch variable, this time using the jscript engine's String.fromCharCode function.

Code: [Select]echo WScript.echo (String.fromCharCode(WScript.arguments(0))); > ascii2string.vbs
For /F "delims=" %%a in ('CSCRIPT //NOLOGO /E:JScript ascii2string.vbs 13') Do Set "CR=%%a"
del ascii2string.vbs

The above replaces this line

for /F %%a in ('copy /Z "%0" nul') DO set "CR=%%a"

OK, it's 3 lines instead of 1 line, (although you can combine them into one using & ) and you need the batch to be in a writeable location, but you can specify which ASCII code you want in the variable e.g. 8 which is BACKSPACE. The trouble with using backspace is you have to count how many you want to use whereas CR just takes you back to the start of the line.

I am working on a way of actually embedding the jscript into the batch so it doesn't need to create and kill a separate temp vbs file and therefore could be run on a non-writeable medium.


Quote from: Salmon Trout on December 04, 2011, 07:05:29 AM
I am working on a way of actually embedding the jscript into the batch so it doesn't need to create and kill a separate temp vbs file and therefore could be run on a non-writeable medium.

Code: [Select]set Dummy=1;/*
echo off
REM The first line of this hybrid JScript/CMD script
REM begins with a command which is common to both script languages
REM and which makes the remainder of the line inconsequential to CMD.
REM CMD sets "Dummy" with the value "1;/*",
REM JScript sets "Dummy" to the value "1" and the /* starts a comment block
REM So the CMD part goes here where JScript will ignore it

setlocal EnableDelayedExpansion

REM PASS this script to the JScript engine to get CR character in a variable
For /F "delims=" %%a in ('cscript //nologo /E:JScript "%~dpnx0" 13') Do Set "CR=%%a"

REM This is a demo
for /L %%N in (1,1,100) do (
  <nul set /p "=!date! !time! %%N!CR!"
  ping -n 2 127.0.0.1 > nul
)
Echo Finished
pause
goto :eof

REM Below is the end of the JScript comment block
REM Under that is the JScript part of the hybrid script
REM We make CMD exit the script with goto :eof so it
REM never gets to the /*
REM NB Unlike VBScript, JScript is case sensitive
REM e.g. WScript needs
REM capital W and capital S and cript in lower
*/
WScript.Echo (String.fromCharCode(WScript.arguments(0)));
Just brilliant S.T.    Great fun, I added a beep as each time was displayed.   Great toy to play with for a while.

Thank you.It might have a practical use e.g. display the progress of some task or other; you could make a progress bar out of characters such as #


Discussion

No Comment Found