I'm writing a windows CMD Batch file, that (for simplified purposes) is supposed to echo every line of this file:
Flash
your
lights
on
and
off
The problem is when it gets to the 4th and 6th words, it ends up running echo on and echo off, which does not actually echo the text, instead it just sets the state of echo to be ON and OFF.
for /F %%a in (DataFile.txt) do echo %%a
The resulting Output is:
Flash
your
lights
and
Is there a way to literally echo the text on and off?
According to this post on DosTips.com, the only safe way to echo any text is to use the odd-looking syntax echo(. So for your command line:
for /F %%a in (DataFile.txt) do echo(%%a
There is the syntax echo. commonly used, but this fails in case there is a file called echo. (no extension) in the current working directory.
The syntax echo/ sometimes used fails if you try to echo a string starting with a question mark (because / followed by ? is interpreted as the /? switch to display the help text for the command).
Try this:
#echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ %userprofile%\Desktop\DataFile.txt"`) do (
set "var=%%a"
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!"
echo(!var!
ENDLOCAL
)
Pause
Check out this link.
on and off, in the context of what you are doing won't work because they are what you call (reserved words in the language) They are used as #echo off or #echo on
The script I posted got around that minor problem. However my lack of of knowledge in batch forces me to conclude my answer as I have no idea of how the script does it.
Related
While "How to echo with different colors in the Windows command line" is widely explained here
How to echo with different colors in the Windows command line
it fails inside a for loop, as chersun already noted:
#JensA.Koch This is awesome. But I have a problem with it running in a for loop. Only the first echo gets properly colored, after that all other ones just print all escape characters instead of changing anything. Batch file is to archive each folder to separate archive, trying to ouput folder name in bold, followed by archiver standard output with findstr filtering. – chersun Apr 22 '18 at 21:36
I am opening a new question as I have not enough reputation to post in the above one.
Only solution I found was to include after the for command (inside the do block) a dummy CMD /C Echo/ as a workaround.
Are there any better ways?
TIA
Edit:
Thanks for the comments, here goes the batch file
out of the block, colors go well.
the issue goes with the CHOICE, if removed problem disapears.
Solution is to include the "empty" CMD
Answer Y to the execution to see failed output
#ECHO OFF
for /F %%a in ('echo prompt $E ^| cmd') do set "_esc=%%a"
set _redon=%_esc%[91m
set _greenon=%_esc%[92m
set _coloff=%_esc%[0m
SET _free=1000
SET _used=2000
ECHO %_redon%!_used!%_coloff% / %_greenon%!_free!%_coloff%
SETLOCAL EnableDelayedExpansion
FOR /L %%A IN (1,1,5) DO (
CHOICE /C YN /T 5 /D N /N /M "Press Y to process %%A"
IF "!ERRORLEVEL!"=="1" (
SET _free=1000
SET _used=2000
REM needed CMD to return proper behaviour
REM CMD /C echo/
ECHO %_redon%!_used!%_coloff% / %_greenon%!_free!%_coloff%
)
)
PAUSE
EXIT
Thanks to #Stephan for beautifying the code.
I can't reproduce:
EDIT:changed to create the ESC symbol in a portable way, thanks to #Aacini
#echo off
cls
for /F %%a in ('echo prompt $E ^| cmd') do set "ESC=%%a"
echo ^<ESC^>[0m %ESC%[0mReset%ESC%[0m
for %%A in (
7,30,31,32,33,34,35,36,37,
40,41,42,43,44,45,46,47,
90,91,92,93,94,95,96,97,
100,101,102,103,104,105,106,107
) Do echo ^<ESC^>[%%Am %ESC%[%%AmTest%ESC%[0m
I'm trying to make a mod loader for a game in batch but I can't get it to work with a nested loop.
The command used is this loadMods.bat mod1.txt mod2.txt ... modN.txt
This is the code I'm using
setlocal EnableDelayedExpansion
set /p outputFile="Output File:"
for %%x in (%*) do (
echo Applying mod from file %%x
for /f "delims=" %%y in (%%x) do echo %%y >> %fileOutput%
)
echo Finished.
pause
The second loop works fine if it's outside the first loop but when I use nested loops I get an The syntax of the command is incorrect. error on the second loop.
As #SomethingDark said, this is caused by a simple typographical issue.
for /f "delims=" %%y in (%%x) do echo %%y >> %fileOutput%
The variable fileoutput was undefined, making the CMD.EXE sees:
for /f "delims=" %%y in (%%x) do echo %%y >>
and it cannot find an argument after >>, causing the error.
By the way, when debugging batch files, I'd recommend:
remove #echo off
run script from CMD.exe
These method shows exactly which command(s) go wrong, making debugging easier.
As you appear only to be copying the contents of several files to a single output file you could probably simplify things a little too.
#Echo Off
If "%~1"=="" Exit/B
Set/P "outputFile= Output File: "
Type %* 2>Nul >"%outputFile%"
Echo( Finished.
Pause
Ensuring the validity of any passed arguments and input string is your responsibility.
You could even possibly bypass the input parameters:
#Echo Off
Set/P "outputFile= Output File: "
Type mod*.txt 2>Nul >"%outputFile%"
Echo( Finished.
Pause
I have a first.properties file and I am reading that file, skipping the first 5 lines and creating a new file with the remaining lines of first.properties. This is working fine. But I am getting spaces for each line in the newly created file. I want to remove these spaces.
I have used the following piece of code:
#echo off
set new=0
setlocal ENABLEDELAYEDEXPANSION
for /F "skip=5" %%L in (first.properties) do (
echo %%L>>NewProjectsInfo.properties
)
endlocal
pause
first.properties is as follows:
name=abcd
number=bcde
address=cdef
mobile=efgh
worklocation=ghij
Please help me out to remove the spaces.
Try this. There can be issues when numbers directly precede the >> characters.
You are not using ENABLEDELAYEDEXPANSION so I removed it too.
#echo off
set new=0
setlocal
for /F "skip=5 delims=" %%L in (first.properties) do (
>>NewProjectsInfo.properties echo %%L
)
endlocal
pause
There is a space after NewProjectsInfo.properties in your code. if that is removed, it works as you expect.
It's sad, but looks like, batch interprets command as entire line & separates out the redirection part. In bash, for example, the command terminates at > symbol itself.
e.g. echo hello >somefile.txt world will put hello world in somefile.txt.
#ECHO OFF
SETLOCAL
(
FOR /f "skip=5 delims=" %%i IN (rltsf.txt) DO CALL :unpad %%i
)>output.txt
FC rltsf.txt output.txt
GOTO :eof
:unpad
ECHO %*
GOTO :eof
This approach seemst to work, but I fancy it may be a little sensitive to line-content. Easier to test if we have representative data...
Why does this batch script work...
#echo off
for /F %%a in ('dir /b F:\Temp\*.txt') do set TestFileName=%%~nxa
echo %FileName%
pause
But this one does not...
#echo off
for /F "usebackq" %%a in ('dir /b "F:\Temp Folder\*.txt"') do set TestFileName=%%~nxa
echo %FileName%
pause
I know that it has something to do with the double quotes that I am using due to the spaces in the folder name. But even after hours of searching the web and reading countless posts that are similar, I can't for the life of me figure out how to fix it. And it is driving me CRAZY!!!
Any help would be greatly appreciated...
Three points here:
1- As "usebackq" imply: Use Back Quotes for command execution, so you must put ` instead of '.
2- Independently of the above, this code:
#echo off
for /F "usebackq" %%a in (`dir /b "F:\Temp Folder\*.txt"`) do set TestFileName=%%~nxa
echo %FileName%
pause
does NOT work either, because the shown variable FileName is NOT the same of the FOR command: TestFileName.
3- I strongly suggest you to NOT use a FOR /F command that execute another command (like DIR) if the base capabilities of simple FOR are enough for your needs. For example:
#echo off
for %%a in ("F:\Temp Folder\*.txt") do set TestFileName=%%~nxa
echo %TestFileName%
pause
Previous code is not just easier to write and understand, but it run faster also.
Finally: previous code "works" in the sense that display just the last file name. If you want to display all names via a variable, then a different approach must be used.
I hope it helps...
Antonio
How you can read a file (text or binary) from a batch file? There is a way to read it in a binary mode or text mode?
Under NT-style cmd.exe, you can loop through the lines of a text file with
FOR /F %%i IN (file.txt) DO #echo %%i
Type "help for" on the command prompt for more information. (don't know if that works in whatever "DOS" you are using)
The FOR-LOOP generally works, but there are some issues.
The FOR doesn't accept empty lines and lines with more than ~8190 are problematic.
The expansion works only reliable, if the delayed expansion is disabled.
Detection of CR/LF versus single LF seems also a little bit complicated.
Also NUL characters are problematic, as a FOR-Loop immediatly cancels the reading.
Direct binary reading seems therefore nearly impossible.
The problem with empty lines can be solved with a trick. Prefix each line with a line number, using the findstr command, and after reading, remove the prefix.
#echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ t.txt"`) do (
set "var=%%a"
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!"
echo(!var!
ENDLOCAL
)
Toggling between enable and disabled delayed expansion is neccessary for the safe working with strings, like ! or ^^^xy!z.
That's because the line set "var=%%a" is only safe with DisabledDelayedExpansion, else exclamation marks are removed and the carets are used as (secondary) escape characters and they are removed too.
But using the variable var is only safe with EnabledDelayedExpansion, as even a call %%var%% will fail with content like "&"&.
EDIT: Added set/p variant
There is a second way of reading a file with set /p, the only disadvantages are that it is limited to ~1024 characters per line and it removes control characters at the line end.
But the advantage is, you didn't need the delayed toggling and it's easier to store values in variables
#echo off
setlocal EnableDelayedExpansion
set "file=%~1"
for /f "delims=" %%n in ('find /c /v "" %file%') do set "len=%%n"
set "len=!len:*: =!"
<%file% (
for /l %%l in (1 1 !len!) do (
set "line="
set /p "line="
echo(!line!
)
)
For reading it "binary" into a hex-representation
You could look at SO: converting a binary file to HEX representation using batch file
You can use the for command:
FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do #echo %i %j %k
Type
for /?
at the command prompt. Also, you can parse ini files!
One very easy way to do it is use the following command:
set /p mytextfile=< %pathtotextfile%\textfile.txt
echo %mytextfile%
This will only display the first line of text in a text file. The other way you can do it is use the following command:
type %pathtotextfile%\textfile.txt
This will put all the data in the text file on the screen. Hope this helps!
settings.ini
name="John"
lastName="Doe"
script.bat
#echo off
for /f "tokens=1,2 delims==" %%a in (settings.ini) do (
if %%a==name set %%a=%%b
if %%a==lastName set %%a=%%b
)
echo %name% %lastName%
Well theres a lot of different ways but if you only want to DISPLAY the text and not STORE it anywhere then you just use: findstr /v "randomtextthatnoonewilluse" filename.txt
Corrected code :
setlocal enabledelayedexpansion
for /f "usebackq eol= tokens=* delims= " %%a in (`findstr /n ^^^^ "name with spaces.txt"`) do (
set line=%%a
set "line=!line:*:=!"
echo(!line!
)
endlocal
pause