Is it possible to edit a line already outputted in Windows batch? - windows

So, I am currently making a "loading screen", and to possibly save some space in my coding, I want to know if you could edit a line already outputted. I would have maybe a bracket [] as one stage of loading, so would it be possible to put one bracket, then wait and see if user presses C (for continue) for 1-2 seconds, and if not go to the next stage ([][])? I currently have a script where [] is set as load and for every stage, I do CLS and then echo %LOAD%[].
In addition, what if I just want to do a status update on a line, such as:
Checking status...
Loading server...
and then
Checking status... OK
Loading server... done
Bonus points if you can find me a character like █ that is compatible with Batch.

You can ommit the CLS and recreating the full screen with the help of set /p, as set /p doesn't output a newline, you can append text.
Normally set /p is for assigning text to a variable inputted by a user, but if you use redirection from NUL it simply outputs text.
#echo off
for /L %%n in (1 1 5 ) do (
<nul set /p ".=[]"
ping -n 2 localhost > nul
)
echo(
echo The end
The status update you asked for, can be handled the same way, as it only appends something to the line.
If you want to change parts of the line or the complete line, you need to move the cursor back or to the beginning of the line.
Both can be done with the backspace character or the carriage return character.
This is a sample which counts on a fixed screen location
setlocal EnableDelayedExpansion
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
for /L %%n in (1 1 1000) do (
<nul set /p ".=%%n!CR!"
)

Creating a blockchar like █ can be done with
setlocal EnableDelayedExpansion
for /F "usebackq tokens=1" %%c in (
`forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo 0xde"`) do (
set BlockChar=%%c
)
echo %BlockChar%
Thanks to dbenham Generate nearly any character, including TAB, from batch

Related

Command prompt FOR /F %%f IN ('DIR /B') fails for first result

I am using a batch file to rename all files in a folder into a numbered list. The code I use is as follow:
set /a Index=1
setlocal enabledelayedexpansion
for /f "tokens=*" %%f in ('dir /b') do (
echo %%f
echo !Index!
rename "%%f" "!Index!.*"
set /a Index+=1
pause
)
The result of the batch file is
G:\Directory A> (
echo
03.jpg
echo 1
rename "
03.jpg" "1.*"
set /a Index+=1
pause
)
03.jpg
1
The filename, directory name, or volume label syntax is incorrect.
Press any key to continue . . .
G:\Directory A> (
echo 04.jpg
echo 1
rename "04.jpg" "1.*"
set /a Index+=1
pause
)
04.jpg
1
The first result ALWAYS contains a line break at the beginning of the file name, which causes the RENAME command to fail. Can anyone tell me what is wrong with my code?
UPDATE
There is the folloging auto-run code set up in the Windows registry:
[HKEY_CURRENT_USER\Software\Microsoft\Command Processor]
"Autorun"="#chcp 65001>nul & prompt $d$s$s$t$_$p$g & cls"
After digging a bit with my batch file, I recognized that this is a problem with the Autorun option that I had set ages ago in Registry that look like this:
[HKEY_CURRENT_USER\Software\Microsoft\Command Processor]
"Autorun"="#chcp 65001>nul & prompt $d$s$s$t$_$p$g & cls"
Apparently the CLS command caused the weird line break to happen. After removing the CLS part from Autorun, the batch file works as it is intended to.
The finding described in the self-answer is very interesting albeit tremendously nasty!
The auto-run code contains the cls command, which sends a single form-feed character (FF, code0x0C) to the console that tells it to clear the screen (the character can be displayed by running cls > con in the console).
When executing cls within a for /F loop, the FF is captured: for /F %F in ('cls') do #echo/%F in the command prompt displays that character.
A for /F loop initiates a new cmd.exe instance to execute the given command line; this is done by preceding cmd /C to the command line.
With auto-run commands set up, they become executed within the for /F loop (due to the unfortunate lack of the /D option, which would prevent them to run).
The auto-run command line from the question has got cls involved, so for /F %F in ('rem') do #echo/%F captures a FF, even though the actual command rem does not return anything.
There are methods to suppress the FF character (note that the following code examples are intended to be placed in a batch-file rather than entered into the console):
Precede the desired command line by echo/& to append a line-break to a potential FF to have an extra line at the beginning and skip that line by for /F:
rem // Precede the desired command with `echo/` and skip the first line:
for /F "skip=1 delims=" %%I in ('echo/^& dir /B') do echo "%%I"
Retrieve a FF first and define it as the eol (end of line) character for for /F, then again prefix the desired command line with echo/& just like before:
rem // Retrieve the form-feed character and ignore lines beginning with a form-feed:
for /F delims^=^ eol^= %%F in ('echo/^& cls') do set "_FF=%%F"
rem // Precede the desired command with `echo/` and use form-feed as `eol` character:
for /F "delims= eol=%_FF%" %%I in ('echo/^& dir /B') do echo "%%I"
A more complex way needs to be gone when the auto-run code may write several arbitrary lines (that may even be empty). For this the number of said lines needs to be determined in order to become able to skip that number of lines later:
rem /* Determine the number of lines that the `AutoRun` code regurgitates, including empty ones;
rem the command line actually executed by `for /F` implicitly using `cmd /C` is as follows:
rem `chcp 437 > nul & echo/& cmd /C echo/| find /C /V ""`
rem this first returns a line-break, to have potential `AutoRun` text separated from the rest;
rem then another `AutoRun` text again with a terminal line-break is generated, but this time
rem piped into `find /C /V ""` in order to count the number of lines;
rem `chcp 437 > nul` is necessary to set the code page for the implicit `cmd.exe` instance,
rem because `find` (just like `more`) may have issues with some particulay Unicode code pages
rem (like 65001, which may be set by the `AutoRun` code): */
for /F %%C in ('chcp 437 ^> nul ^& echo/^& cmd /C echo/^| find /C /V ""') do set /A "SKIP=%%C" 2> nul
if %SKIP% gtr 0 (set "SKIP=skip=%SKIP%") else set "SKIP="
rem // Precede the desired command with `echo/` and skip as many lines as necessary:
for /F "%SKIP% delims=" %%I in ('echo/^& dir /B') do echo "%%I"

Batch File VT100 implementation

I am trying to stop screen flicker when it comes to my batch program that is used to display a text file on the screen. It has to update and the only way I have come up with is to loop the program and clear the screen.
This is my current code.
::Begin the refresh loop
::---------------------------------------------------------------
:Refresh
type "%ud%\ChatTerminal\Msg.txt
Sleep 1
cls
Goto Refresh
:Break Refresh
::---------------------------------------------------------------
::Refresh Loop Ends
::---------------------------------------------------------------
After some research I came to this post:
How do I remove flickering from a batch file animation?
The issue is that I would not know where to start with the implementation.
The escape character for VT sequences can be defined using:
For /F %%e in ('echo prompt $E^|cmd')Do set "\E=%%e"
Depending on the format and contents of each .txt file, flicker free animation could be as simple as returning the cursor to screen home between each 'frame':
<nul set /p "=%\E%[1;1H"
Edit
Should the source file/s be of differing line lengths or line counts, then each line needs to be read in and the VT sequence %\E%[K prepended to clear the remainder of the line and %\E%[0J after each file to clear the remainder of the console screen from the cursor location.
An example, which creates files to animate:
(Note: %\E%[E emits a line feed )
Anim.bat
#Echo off & CD /D "%~dp0"
For /f %%e in ('Echo Prompt $E^|cmd') Do set "\E=%%e"
<nul Set /P "=%\E%[?25l"
Set /A "delay=4", "Files=0","FC=1"
Setlocal EnableExtensions EnableDelayedExpansion
For %%i in (5 6 7 8 9 10 11 12 13 14 15 14 13 12 11 10 9 8 7 6 5)Do (
Set /A Files+=1
Call :CreateCube %%i "infile!Files!.txt"
)
For /L %%i in ()Do (
for /f "tokens=1-4 delims=:.," %%a in ("!time: =0!") do set /a "t2=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100, tDiff=t2-t1"
if !tDiff! lss 0 set /a tDiff+=24*60*60*100
if !tDiff! geq !delay! (
Set /A "FC=FC %% Files + 1"
<nul Set /P "=%\E%[1;0H"
If !FC! GTR 10 (If !Offset! GTR 1 Set /A "Offset-=1")Else Set "offset=!FC!"
(For /f "Delims=" %%G in (infile!FC!.txt)Do <nul set /P "=%\E%[K%\E%[!offset!G%%G%\E%[E") > Con
<nul Set /P "=%\E%[0J"
set /a t1=t2
)
)
:CreateCube <size>
:# golfed script for outputting a shaded multi color cube
:# https://codegolf.stackexchange.com/a/224741/92319
#echo off&Cls&Set $=Set &CHCP 65001 > nul
If "%~1"=="" (Echo(%~n0 Integer Outfile.ext&Exit /B)
If "%~2"=="" (Echo(%~n0 Integer Outfile.ext&Exit /B)
(<Nul Set /p "=%\E%7")>"%~2"
%$%/A x=%1,h=x*2,z=0
%$%F=For /L %%a in (1 1 &%$%P=^<nul set/p &%$%C= If %%y LEQ %1
((%f:a=y%!h!)Do (%$%/a w=x-z
%F%!w!)Do %P%"=%\E%7 "
%F%!z!)Do%C%(%P%"=%\E%[38;2;0;120;%%a0m_|")Else %P%"=%\E%[4m%\E%[38;2;120;0;%%a0m\\%\E%[0m"
%F%%1)Do%C%(%P%"=%\E%[38;2;120;0;%%a0m▲▼")Else %P%"=%\E%[38;2;0;120;%%a0m_\"
%C:EQ=SS%(%$%/A z+=1)Else%C:If=If not%%$%/A z-=1)&Echo(%\E%[0m))>"%~2"
Note: the time elapsed operation used for framerate originates from Dave Benhams snake.bat
Implementation of framerate control in a repeating for /l infinate loop is strongly recommended to facilitate a smooth animation - failure to do so will result in the animation appearing jagged / choppy as it occurs at a pace the eye cant follow
T3RR0R's solution overwrites existing lines without deleting the rest of the old line. So when the new line is shorter, the rest of the old line keeps showing.
That could be solved by writing the file line by line, deleting the rest of the line. Sadly that slows things down and thus re-introduces the flicker (at least for files with more than one line).
As an alternative, only write the file, if it has changed. It still flickers, but now just when the file is updated. After displaying the file, unset the archive attribute. Whenever Windows writes to the file, it sets the attribute again, which we use to determine if the file has changed.
#echo off
set "file=%ud%\ChatTerminal\Msg.txt"
:loop
attrib "%file%"|findstr /b "A" >nul && (
cls
type "%file%"
attrib "%file%" -a
)
timeout 1 >nul
goto :loop
Bonus: this doesn't use Escape codes, so it runs on every Windows version (possibly there are a few deprecated Windows versions that didn't have timeout by default, but it can be replaced with ping when needed)
Seems like all you are trying to do is TAIL a file and print the those new lines to the screen. You can use this method to accomplish that.
#echo off
call :Read <"file.txt"
GOTO :EOF
:Read
set "line="
set /p "line="
if defined line (
echo %line%
)
goto :Read

Windows Command Prompt print text file with delay

I have no experience with command prompt whatsoever, but I'd like to make a batch script (for fun and learn) that would print a text file from a given location, line by line, with a 1 second delay.
I would also want it to be able to pause/unpause when I press a designated key (ex: space) and feed me an extra line (on top of those already programmed to run) when I press another key (ex: enter).
I know I can add a 1 second delay by pinging localhost ping -n 5 127.0.0.1 > nul
And I know I can see the content of a text file using more text.txt, but I don't know how to iterate through an entire text file until EOF is met and I don't know how to pause/resume and feed extra line.
Hope it doesn't sound stupid or out of scope in this context, but it's just something that interests me right know and I know a lot people here have the knowledge to do this.
1) If you have experience in programming, you will know using a for loop is the most common way to do things one by one, e.g. line by line.
2) You can simply use ping localhost -n 2 >nul for 1 second delay, the 2 in the ping is not indicating 2 seconds, but 1 second instead. (I have no idea about that, just get used to it)
3) You can't pause/unpause when cmd is pinging, I mean there's no way to force the program to pause/unpause because the delay process is executed in just a line of code! Or you can magically add some code into it like ping localhost -n 2 pause while(KeyDown(SPACE)) >nul (just kidding :) )
4) Extra lines? Hmm... Remember batch is not a powerful language so... Yeah
Here is a simple code to print text line by line each second in a .txt file
for /f %%a in (your_text.txt) do (
echo %%a
ping localhost -n 2 >nul
)
You could do it synchronously with choice /t 1 (for a 1-second timeout) and some key other than Spacebar. Perhaps P for Pause?
#echo off
setlocal
set "textfile=notes.txt"
echo Hit P to pause / resume, Q to quit.
echo;
for /f "tokens=1* delims=:" %%I in ('findstr /n "^" "%textfile%"') do (
echo(%%J
choice /t 1 /c €pq /d € >NUL
if errorlevel 3 exit /b 0
if errorlevel 2 (
pause >NUL
ping -n 1 -w 750 169.254.1.1 >NUL
)
)
exit /b 0
Unfortunately, choice only allows a-z, A-Z, 0-9, and extended characters 128-254. There's no way to make it listen for Enter or Space. And choice is the only Windows command of which I'm aware that'll accept a single keypress and do something meaningful based on which key was pressed.
I think you'll have to use some sort of compiled language (or possibly PowerShell with a .NET class?) to listen for keypress events on the console. You could probably do it in JavaScript, but you'd have to display your output in a web browser or HTA window.
A "scrolling editor"? It is a crazy idea, isn't it? I LIKE IT! ;-) I adopted your project and add some points...
#echo off
rem ScrollEditor.bat: "dynamic" very simple line editor
rem Antonio Perez Ayala aka Aacini
if "%~1" neq "" if "%~1" neq "/?" goto begin
echo ScrollEditor.bat filename.ext
echo/
echo File lines will be continually scrolling, one per second.
echo/
echo You may pause the scroll via P key. In the "paused" state, the last displayed
echo line is named "current line", and the following commands are active:
echo/
echo #L Return/advance the listing to line #; continue the scroll from there.
echo [#]D Delete [from previous line # up to] current line.
echo I Insert lines after current line; end insert with *two* empty lines.
echo P End "paused" state; continue the scroll from current line on.
echo E End edit and save file, keep original file with .bak extension.
echo Q Quit edit, not save file.
goto :EOF
:begin
if not exist %1 echo File not found & goto :EOF
rem Load file lines into "line" array
set /P "=Loading file... " < NUL
setlocal DisableDelayedExpansion
for /F "tokens=1* delims=:" %%a in ('findstr /N "^" %1') do (
set "line[%%a]=%%b"
set "lastLine=%%a"
)
echo last line: %lastLine%
echo To pause scrolling, press: P
echo/
setlocal EnableDelayedExpansion
set "validCommands=LDIPEQ"
set currentLine=1
:command-P End "paused" state
:ScrollLine
if %currentLine% gtr %lastLine% (
set "currentLine=%lastLine%"
echo EOF
goto GetCommand
)
set "num= %currentLine%"
echo %num:~-4%: !line[%currentLine%]!
set /A currentLine+=1
choice /C PC /N /T 1 /D C >NUL
if errorlevel 2 goto ScrollLine
rem Enter paused state
set /A currentLine-=1
:GetCommand
echo/
set /P "command=Command [#L,#D,I,P,E,Q]? "
set "letter=%command:~-1%"
if "!validCommands:%letter%=!" equ "%validCommands%" goto GetCommand
goto command-%letter%
:command-L Go to line #; continue scrolling
set "currentLine=%command:~0,-1%"
goto ScrollLine
:command-D Delete from line # to current line
set "prevLine=%command:~0,-1%"
if not defined prevLine set "prevLine=%currentLine%"
rem Move lines after last deleted one into deleted lines
set /A currentLine+=1, newCurrent=prevLine-1, lines=currentLine-prevLine
for /L %%j in (%currentLine%,1,%lastLine%) do (
set "line[!prevLine!]=!line[%%j]!"
set /A prevLine+=1
)
set /A currentLine=newCurrent, lastLine=prevLine-1
if %currentLine% equ 0 set "currentLine=1"
echo %lines% line(s) deleted (current=%currentLine%, last=%lastLine%)
goto GetCommand
:command-I Insert lines after current one
echo End insert with *two* empty lines
echo/
rem Read new lines into "ins" array
set "newLine=%currentLine%"
:insertLine
set "line="
set /A newLine+=1
set "num= %newLine%"
set /P "line=+%num:~-3%: "
set "ins[%newLine%]=!line!"
rem The most complex part: end in two empty lines...
if not defined line (
set /A newLine+=1
set "num= !newLine!"
set /P "line=+!num:~-3!: "
if defined line (
set "ins[!newLine!]=!line!"
) else (
set /A newLine-=2
)
)
if defined line goto insertLine
rem Move old lines to new place to make room for new lines
set /A lines=newLine-currentLine, currentLine+=1, newLast=lastLine+lines
for /L %%j in (%lastLine%,-1,%currentLine%) do (
set "line[!newLast!]=!line[%%j]!"
set /A newLast-=1
)
rem Insert new lines in old place
for /L %%j in (%currentLine%,1,%newLine%) do set "line[%%j]=!ins[%%j]!"
set /A lastLine+=lines, currentLine=newLine
echo %lines% line(s) inserted (current=%currentLine%, last=%lastLine%)
goto GetCommand
:command-E End edit, save file
echo Saving file...
move /Y %1 "%~N1.bak"
(for /L %%i in (1,1,%lastLine%) do echo(!line[%%i]!) > %1
:command-Q Quit edit
echo End edit
This program have multiple problems: don't check for valid input in commands, may have problems with special Batch characters and if the first character of a line is a colon, eliminate it. However, it is a good starting point for this project!
Perhaps you may be interested in this similar project.

Batch File - Insert Line into file

I'm trying to insert a line into a file using the following code (from Write batch variable into specific line in a text file)
#echo off
setlocal enableextensions enabledelayedexpansion
set inputfile=variables.txt
set tempfile=%random%-%random%.tmp
copy /y nul %tempfile%
set line=0
for /f "delims=" %%l in (%inputfile%) do (
set /a line+=1
if !line!==4 (
echo WORDS YOU REPLACE IT WITH>>%tempfile%
) else (
echo %%l>>%tempfile%
)
)
del %inputfile%
ren %tempfile% %inputfile%
endlocal
My problem is the file has comment lines (which start with semicolons) which need to be kept
; directory during network startup. This statement must indicate a local disc
; drive on your PC and not a network disc drive.
LOCALDRIVE=C:\TEMP;
; PANELISATION PART/NET NAMING CONVENTION
; When jobs are panelised, parts/nets are renamed for each panel step by
When I run the batch file, it ignores the semicolon lines, So I only get:
LOCALDRIVE=C:\TEMP;
What do I need to do to keep the semicolon lines?
The EOL option determines what lines are to be ignored. The default value is a semicolon. If you know a character that can never appear in the first position of a line, then you can simply set EOL to that character. For example, if you know a line can't start with |, then you could use
for /f "eol=| delims=" %%l in (%inputfile%) do ...
There is an awkward syntax that disables EOL completely, and also disables DELIMS:
for /f delims^=^ eol^= %%l in (%inputfil%) do ...
Note that FOR /F always discards empty lines, so either of the above would result in:
; directory during network startup. This statement must indicate a local disc
; drive on your PC and not a network disc drive.
LOCALDRIVE=C:\TEMP;
; PANELISATION PART/NET NAMING CONVENTION
; When jobs are panelised, parts/nets are renamed for each panel step by
A trick is used if you want to preserve empty lines. Use FIND or FINDSTR to insert the line number before each line, and then use expansion find/replace to remove the line number. Now you know the line never begins with ;, so you can ignore the EOL option.
for /f "delims=" %%L in ('findstr /n "^" "%inputfile%"') do (
set "ln=%%L"
set "ln=!ln:*:=!"
REM You now have the original line, do whatever needs to be done here
)
But all of the above have a potential problem in that you have delayed expansion enabled when you expand the FOR variable, which means that any content containing ! will be corrupted. To solve this you must toggle delayed expansion on and off within the loop:
setlocal disableDelayedExpansion
...
for /f "delims=" %%L in (findstr /n "^" "%inputfile%") do (
set "ln=%%L"
setlocal enableDelayedExpansion
set "ln=!ln:*:=!"
REM You now have the original line with ! preserved, do whatever needs done here
endlocal
)
Also, when ECHOing an empty line, it will print out ECHO is off unless you do something like
echo(!ln!
It takes time to open and position the write cursor to the end every time you use >> within the loop. It is faster to enclose the entire operation in one set of parentheses and redirect once. Also, you can replace the DEL and REN with a single MOVE command.
Here is a final robust script:
#echo off
setlocal disableDelayedExpansion
set "inputfile=variables.txt"
set line=0
>"%inputfile%.new" (
for /f "delims=" %%L in (findstr /n "^" "%inputfile%") do (
set "txt=%%L"
set /a line+=1
setlocal enableDelayedExpansion
set "txt=!txt:*:=!"
if !line! equ 4 (
echo New line content here
) else (
echo(!txt!
)
endlocal
)
)
move /y "%inputfile%.new" "%inputfile%" >nul
endlocal
That is an awful lot of work for such a simple task, and it requires a lot of arcane knowledge.
There is a much quicker hack that works as long as
your first 4 lines do not exceed 1021 bytes
none of your first 3 lines have trailing control characters that need to be preserved
the remaining lines do not have <tab> characters that must be preserved (MORE converts <tab> into a string of spaces.
#echo off
setlocal enableDelayedExpansion
set "inputfile=variables.txt"
>"%inputfile%.new" (
<"%inputfile%" (
for /l %%N in (1 1 3) do (
set "ln="
set /p "ln="
echo(!ln!
)
)
echo New line content here
more +4 "%inputfile%"
)
move /y "%inputfile%.new" "%inputfile%"
That is still a lot of work and arcane knowledge.
I would use my JREPL.BAT utility
Batch is really a terrible tool for text processing. That is why I developed JREPL.BAT to manipulate text using regular expressions. It is a hybrid JScript/batch script that runs natively on any Windows machine from XP onward. It is extremely versatile, robust, and fast.
A minimal amount of code is required to solve your problem with JREPL. Your problem doesn't really require the regular expression capabilities.
jrepl "^" "" /jendln "if (ln==4) $txt='New content here'" /f "variables.txt" /o -
If used within a batch script, then you must use call jrepl ... because JREPL.BAT is also a batch script.
By default, the FOR command treats ; as the end-of-line character, so all those lines that start with ; are being ignored.
Add eol= to your FOR command, like this:
for /f "eol= delims=" %%l in (%inputfile%) do (
It looks like you're echoing just the line delimiter, not the whole line:
echo %%l>>%tempfile%
I'm rusty on ms-dos scripts, so I can't give you more than that.

Echoing in the same line

I had a look at the previous questions of your db and I didn't try an answer, but I try.
I would like to write the following lines code:
echo Executing backup....
backup procedure
echo Ok
but the output should be:
Executing backup... Ok
That's possible?!
I suppose you are using dos/nt-batch.
It is possible with the set /p command, because set /p doesn't print a CrLf
set /p "=Executing backup...." <nul
echo OK
Also it's possible to erase the line with a CR character.
It's important to know that whitespace characters at the front of an set /p are ignored (in Vista, not in XP), so the !cr! has to placed later or at the end.
A CR can only be displayed with delayedExpansion, because %cr% works, but CR characters are removed in the percent expansion phase(or directly after this phase), but not in the delayed expansion phase.
Example of a counter which use only one line for displaying
#echo off
setlocal EnableDelayedExpansion EnableExtensions
call :CreateCR
for /l %%n in (1,1,10000) do (
set /P "=Count %%n!CR!" <nul
)
echo(
goto :eof
:CreateCR
rem setlocal EnableDelayedExpansion EnableExtensions
set "X=."
for /L %%c in (1,1,13) DO set X=!X:~0,4094!!X:~0,4094!
echo !X! > %temp%\cr.tmp
echo\>> %temp%\cr.tmp
for /f "tokens=2 usebackq" %%a in ("%temp%\cr.tmp") do (
endlocal
set cr=%%a
goto :eof
)
goto :eof
EDIT: Explanation, how the variable cr is created (Done with a trick)
After setting variable X to a single dot (the character itself is unimportant), it is repeated to become 8188 characters by way of for /L %%c in (1,1,13) DO set X=!X:~0,4094!!X:~0,4094!
Then the variable, two spaces and both a CR and LF are echoed into a file with echo !X! > %temp%\cr.tmp (Notice the two spaces between the !X! and the > and the natural line endings echo amends internally)
We now have 8192 characters, but the data buffer can only hold 8191 characters, so the last character (the linefeed) will be dropped!
In the next line echo\>> %temp%\cr.tmp, another CR/LF set is appended to the file (the \ in the command is just to output nothing bar the carriage return and line feed, as echo by it's self will output ECHO is ON/OFF), that's important, as a single CR can't be read at the end of a line (More later).
So the file now contains <8188 .'s><SPACE><SPACE><CR><CR><LF>
The for /f "tokens=2 usebackq" %%a in ("%temp%\cr.tmp") do reads the second token, the delimters are standard space and tab, so the second token is only a single CR, as the following CR/LF is removed as standard line ending.
Finally the endlocal is used to return to an environment without the temporary variables X, c and a existing (As with the endlocal in brackets, it allows the setting of cr before the endlocal actually takes affect at the end of the brackets (could also be written as for /f "tokens=2 usebackq" %%a in ("%temp%\cr.tmp") do endlocal&set cr=%%a&goto :eof)
Additionally
This was my first way to create a CR character, but it needs some time and a temporary file.
Later I saw a simpler method of retrieving the CR from a copy /z command.
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
Try this on Posix system (Linux)
echo -n "Executing backup.... "
echo -n "backup procedure "
echo "Ok"
It is much harder on Windows. You will need to use something like this:
#echo off
echo|set /p ="Executing backup...."
echo|set /p =" backup procedure"
Check this post: http://www.pcreview.co.uk/forums/showpost.php?s=1a20b16775d915998b30bd76a0ec5d35&p=4432915&postcount=7.
It's a bit of a hack, but here is an article describing how to do it for Windows.
From the article, the final result (edited for your setup) looks like this:
SET /P var=Backing up
%Result%....<NUL
Backup_process %Result% >NUL 2>&1
IF ERRORLEVEL 1
ECHO FAIL
ELSE
ECHO OK
I've done something similar using a VBScript.
Put this code in EchoNoNewline.vbs:
If WScript.Arguments.Named.Exists("TEXT") Then
WScript.StdOut.Write WScript.Arguments.Named.Item("TEXT")
End If
From your batch file, use the script like this:
CSCRIPT EchoNoNewLine.vbs //NOLOGO /TEXT:"Executing backup...."
backup procedure
CSCRIPT EchoNoNewLine.vbs //NOLOGO /TEXT:"Ok"
at What does a forward slash before a pipe in cmd do to remove the line ending of an echo?
the best suggestion is:
to echo text without a linefeed is very inefficient, as a pipe creates two new instances of cmd.exe.
It's much simpler and faster to use
<nul set /p "=My Text"
The redirect from NUL will also stop the waiting for user input.

Resources