Batch script: Format text echoed inside a loop - batch-file

In a batch script, inside a loop, i have to echo multiple statements to command prompt.
I want to format (change foreground/background color) of statements inside the loop, differently.
Script as below -
FOR /d %%b IN ("%source%\*") DO (
echo ****** 1111 ********
cd "%%b"
git status
echo ****** 2222 ********
cd ..
)
Loop will run 4-5 times, exact count will be determined only at runtime.
On every execution of loop, ****** 1111 ******** should print in formatted color and rest of statements after it should print as it is (normal).
I did tried to write it like
FOR /d %%b IN ("%source%\*") DO (
echo [101;93m ****** 1111 ********
cd "%%b"
git status
echo [0m ****** 2222 ********
cd ..
)
But first time formatting applies to ****** 1111 ******** and then escape characters and color codes are printed on cmd and formatting changes are not applied on subsequent executions of loop.
I am a novice in this area, any help would be highly appreciated.

Related

BATCH file reloading autorun buffer

There are things that we prefer not to understand in order to have an easier life to live.
But this is not something I can choose...
I made a batch file (or macro.doskey) to get the charset code. And it worked perfectly for a long time...
Basically it runs chcp:
> chcp
Code page active: 850
and then wraps the return before and after the colon
assigning what comes after to a variable:
FOR /F "tokens=1,* delims=:" %%s in ('CHCP') do (
#ECHO %%t
IF NOT "%1" == "" (SET %1=%%t)
)
For example:
> getCHCP.bat myVar
850
> ECHO %myVar%
850
However it started to lock, waiting for ENTER or displaying several echo messages. For example:
> getchcp myVar
ECHO is off.
ECHO is off.
ECHO is off.
ECHO is off.
ECHO is off.
ECHO is off.
ECHO is off.
ECHO is off.
850
I started to mix until I decided to change the ECHO %%t to ECHO %%s, and guess what?
No, is that the Bill Gates skull? Is it an easter egg from Microsoft? A virus?
No, none of that, this is just my autorun's welcome message.
This can be configured in
<[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor]autorun>
In my case I called a batch file which, among other things, gives several echos showing this skull on the screen.
But the question is, why does it act like it reloads the autorun in background
when I've already opened the command prompt?
And why does it leave
everything in the buffer so that %%s pulls it again to the (Page code active) ':'?
And why are
you giving lots of ECHO is off on %%t when the only thing after
Code page active: is a number?
And the most important: How I solve it?
It's obvious, you already point to the problem.
this is just my autorun's welcome message.
This can be configured in
<[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor]autorun>
The line FOR /F %%s in ('CHCP') ... start CHCP but that will be done in a NEW child cmd.exe instance.
And a NEW cmd.exe instance runs the autorun command!
Just before it starts your chcp.
You can disable the autorun at all, or add some code to detect the difference between a new cmd.exe instance for the user against a new instance from a FOR /F.
Put this code at the start of your autorun batch file
#echo off
setlocal EnableDelayedExpansion
REM *** ALWAYS make a copy of the complete CMDCMDLINE, else you destroy the originial!!!
set "_ccl_=!cmdcmdline!"
REM *** %1 contains only data, when the script itself was called from the command line
if "%~1" NEQ "" (
goto :direct_call
)
REM *** The check is necessary to distinguish between a new cmd.exe instance for a user or for a "FOR /F" sub-command
if "!_ccl_:~1,-2!" == "!comspec!" (
REM ***** INTERACTIVE ****
REM *** Show your skull or something else
)
exit /b

Can't enter a variable in DOS

I'm trying to run a batch file in vDOS (DOS emulator), where I want the user to input two variables. Every time I run the file, it doesn't let me enter the variables.
SET /P in=Input:
SET /P out=Output:
What I expected to happen was that It'd let me enter the input for the variables.
Instead, it executes both of the commands as they are (without letting me enter the input).
Windows cmd and MS-DOS are very different things and one of the differences is the set command. In MS-DOS the only form of set is set variable=value. There are neither set /A, set "variable=value" nor set /P.
set /P is a feature of Windows NT's cmd.exe. In DOS you must use 3rd party software to get user input and store in a variable. Here are some solutions
SENVAR.COM
SENVAR INPUT Input string:
EDITVAR and CHOOSE
editvar -p "Input string: " INPUT
FC.COM
#echo off
:: based on batch from PC Magazine June 27, 1995 page 248
:: this version puts temps in C:\DOS dir and shortens var names
:: User input is returned in variable STR
:input
> C:\DOS\en#er.bat fc con nul /lb1 /n|date|find " 1: "
> C:\DOS\enter.bat echo set str=
>>C:\DOS\enter.bat echo :loop
>>C:\DOS\enter.bat echo if not '%%str%%==' set str=%%str%% %%5
>>C:\DOS\enter.bat echo if '%%str%%==' set str=%%5
>>C:\DOS\enter.bat echo shift
>>C:\DOS\enter.bat echo if not '%%5==' goto loop
call en#er.bat
del C:\DOS\enter.bat
del C:\DOS\en#er.bat
ANSI.SYS
#ECHO OFF
REM * Ask for USeR INPUT and store it in variable USRINPUT
REM * Assumes ANSI.SYS is loaded
REM * Written by Rob van der Woude
SET USRINPUT=
REM * Turn on ANSI key translation (translate Enter
REM * key to F6+Enter sequence) and ask for input:
ECHO ←[13;0;64;13pEnter one word only . . .
REM * Copy entered text to temporary file:
COPY CON %TEMP%.\~USRINP.TMP
REM * Turn off ANSI key translation and clear irrelevant screen output:
ECHO ←[13;13p←[3A←[K←[1B←[K←[1B←[K←[2A
REM * Add empty line to temporary file. The empty line
REM * will be used to stop DATE asking for new date.
ECHO.>> %TEMP%.\~USRINP.TMP
ECHO.>> %TEMP%.\~USRINP.TMP
REM * Create a temporary batch file that will store the
REM * entered text into the environment variable USRINPUT:
TYPE %TEMP%.\~USRINP.TMP | DATE | FIND "):" > %TEMP%.\~USRINP.BAT
REM * Create more temporary batch files. Add
REM * more command line parameters if necessary,
REM * as in: ECHO SET USRINPUT=%%3 %%4 %%5 %%6 %%7 %%8 %%9>CURRENT.BAT
ECHO SET USRINPUT=%%3>CURRENT.BAT
REM * VOER.BAT and TYP.BAT are replacements for CURRENT.BAT for Dutch
REM * DOS versions; add your own language versions if necessary:
ECHO SET USRINPUT=%%6>VOER.BAT
ECHO SET USRINPUT=%%4>TYP.BAT
REM * This temporary batch file now sets the variable USRINPUT:
CALL %TEMP%.\~USRINP.BAT
REM * Display the result:
ECHO You typed: ←[1m%USRINPUT%←[0m
ECHO.
PAUSE
REM * Finally, clean up the mess of temporary files:
FOR %%A IN (%TEMP%.\~USRINP.BAT %TEMP%.\~USRINP.TMP VOER.BAT TYP.BAT CURRENT.BAT) DO DEL %%A
The ← is the escape character (27h)
In case you just want to get simple answers like Y/N then CHOICE.COM is designed for that purpose
See also
MS-DOS 6.22 Batch File User Input to Environment Variable
Prompt for variable in DOS 7.1
/P didn't get introduced until Windows 2000 or NT. Legacy MS-DOS or equivalent won't have it. https://www.computerhope.com/sethlp.htm

Unknown glitch in batch

I need help with an unknown issue in a recent batch file executed on Windows 10.
Proper function:
I am trying to make a math quiz which generates two numbers, a basic operand (+-x/), finds the answer, then checks it against an answer from a user. Additionally, the program is made to track certain information after a user has put in their answer. (Question number, the problem and answer, and the users response.)
My issue:
In certain scenarios the program will display the problem/answer in the "game" window rather than writing the problem/answer in the text file as intended.
The command is:
echo [Q]%m%>>"C:\Users\%username%\Desktop\%fname%.txt"
It is comment marked in the code below.
What I've done to fix the issue?
After testing for a descent while I discovered the issue seemed to revolve around the portion where it tries to move a problem/answer combo with division as the operation. This helped, but the issue started randomly popping up throughout future attempts to debug.
While I feel it is a bit frowned upon to ask two things at once I have two more issues.
Why does an operation like %a%%b%%c%=%d% (a,c,d being numbers and b being a /) break a certain command in my code consistently and how can I fix it?
Why does the same issue still randomly appear even if I erase all traces of division / which seems to cause my issue in the first place.
Here is the batch file:
::Initialization
#echo off
set /a prb=3
set file=Stat
set sss=s.
if %prb%==1 set tst=.
echo.
echo Welcome to math fire, you will get randomly generated
echo multiplication, addition, and subtraction problems. You
echo will go through a specified number before the game ends
echo and this window closes. You will be tracked in a file on
echo your desktop. You will have %prb% problem%sss%
echo.
pause
CLS
echo Get ready
timeout 5
set start=%time%
CLS
set /a num=1
set /a good=0
set /a bad=0
::===========================Set up beggining of stat file.
echo =-=-=-=-=-=>>"C:\Users\%username%\Desktop\%fname%.txt"
echo ===Start===>>"C:\Users\%username%\Desktop\%fname%.txt"
echo =-=-=-=-=-=>>"C:\Users\%username%\Desktop\%fname%.txt"
echo.>>"C:\Users\%username%\Desktop\%fname%.txt"
::===================================Main Body============
::[A] Num1 [B] Operator [C] Num2 [D] Answer [E] The problem [M] Problem and answer
:main
set /a a=%random% %% 30 + 1
::To remove the division section I changed the 4 below to 3
set /a b=%random% %% 4 + 1
set /a c=%random% %% 20 + 1
if %b%==1 set b=+
if %b%==2 set b=-
if %b%==3 set b=*
if %b%==4 set b=/
set /a d=%a%%b%%c%
set e=%a%%b%%c%
echo.
echo =============================%e%=?
echo.
timeout 1
set /p ans=+++++++++++++++++++++++++++++Answer:
set m=%e%=%d%
echo ===%num%===>>"C:\Users\%username%\Desktop\%fname%.txt"
::The following line is the glitching code
echo [Q]%m%>>"C:\Users\%username%\Desktop\%fname%.txt"
echo [A]%ans%>>"C:\Users\%username%\Desktop\%fname%.txt"
echo.>>"C:\Users\%username%\Desktop\%fname%.txt"
if %ans%==%d% goto p
CLS
echo.
echo -----------------------------Incorrect
set /a bad=%bad%+1
goto re
:p
CLS
echo.
echo -----------------------------Correct
set /a good=%good%+1
goto re
:re
if %num%==%prb% goto end
set /a num=%num%+1
goto main
:end
echo ===========>>"C:\Users\%username%\Desktop\%fname%.txt"
echo.>>"C:\Users\%username%\Desktop\%fname%.txt"
echo [Start]%start%>>"C:\Users\%username%\Desktop\%fname%.txt"
echo [-End-]%time%>>"C:\Users\%username%\Desktop\%fname%.txt"
echo [Right]%good%>>"C:\Users\%username%\Desktop\%fname%.txt"
echo [Wrong]%bad%>>"C:\Users\%username%\Desktop\%fname%.txt"
echo.>>"C:\Users\%username%\Desktop\%fname%.txt"
echo =-=-=-=-=-=>>"C:\Users\%username%\Desktop\%fname%.txt"
echo ===-End-===>>"C:\Users\%username%\Desktop\%fname%.txt"
echo =-=-=-=-=-=>>"C:\Users\%username%\Desktop\%fname%.txt"
echo.>>"C:\Users\%username%\Desktop\%fname%.txt"
CLS
echo.
echo.
echo.
echo Congrats, check your desktop for your play info.
echo.
echo.
echo.
pause
exit
Use the syntax
>>"%filename1%" echo [Q]%m%
(my testfiles are allotted in variables)
Noting that m will contain a string such as 13/14=0
The character just before a redirector redirects the logical device number. You can get around this by moving the redirction to the start of the command or inserting a space before the redirector or using
>>"%filename1%" (
echo [Q]%m%
echo something else
echo more text
)
or
(
echo [Q]%m%
echo something else
echo more text
)>>"%filename1%"
which does the same thing - gather the output of the echoes and redirect the sum-output to the file.
Oh, BTW - batch does integer mathematics, so 13/4=3 - no decimals.

Call batch within batch?

How do I call multiple batch files within a single batch? When I try it always goes to the same one or none at all and closes window.
#echo off
:MENU
title MENU0
Echo 1 - Select Menu 1
Echo 2 - Select Menu 2
Echo 0 - Exit
Echo.
SET /P choice=Type the number or letter of task you want, then press ENTER:
IF %choice%==1 GOTO 1
IF %choice%==2 GOTO 2
IF %choice%==0 EXIT
:1
call %userprofile%\desktop\\Menu1.bat
:2
call %userprofile%\desktop\Menu2.bat
There are several issues with provided batch code in question.
The first one is that after processing of the batch file called with command CALL finished, the processing of current batch file continues with the next command respectively line, except the called batch file contains itself the command EXIT without parameter /B as in this case the command processor terminates itself independent on calling hierarchy.
For details about CALL behavior see answers on:
How to call a batch file in the parent folder of current batch file?
In a Windows batch file, can you chain-execute something that is not another batch file?
The second issue is that folder path assigned to environment variable USERPROFILE could contain 1 or more spaces (default on Windows 2000/XP, possible on later Windows versions depending on user name). Therefore always enclose a string referencing USERPROFILE or USERNAME in double quotes.
The third and most difficult to handle issue is that the user of a batch file on prompt with set /P has the freedom to enter anything and not just what the writer of the batch file suggests.
For example
SET /P choice=Type the number or letter of task you want, then press ENTER:
IF %choice%==1 GOTO 1
results in an exit of batch processing caused by a syntax error if the batch user hits just RETURN or ENTER without entering anything at all and the environment variable choice is not already defined with a useful string because in this case the next line to process by command processor is:
IF ==1 GOTO 1
It is good practice to define the environment variable with a default value before set /P as this value is kept when the batch user just hits RETURN or ENTER.
A batch user has also the freedom on using set /P to enter anything including syntax critical characters like " or < or | or > and others by mistake or intentionally (for breaking batch processing by a syntax error).
Therefore it is in general better for menus in batch files to use the command choice (Microsoft article) because then the batch user can enter only what the writer of the batch file offers. But CHOICE is available only by default for Windows Server 2003 and later Windows. And there are different versions of choice (SS64 article with additional information) with a different set of options. So it depends on which Windows version(s) the batch file is designed for if CHOICE can be used at all.
It is also not good to name an environment variable or a label like a command although possible. Therefore choice is not a good name for an environment variable.
Here is a commented batch file with a code which avoids all those issues.
#echo off
:MainMenu
setlocal EnableDelayedExpansion
title MENU0
cls
echo 1 - Select Menu 1
echo 2 - Select Menu 2
echo 0 - Exit
echo.
rem Define 0 as default value in case of user just hits RETURN or ENTER.
set "UsersChoice=0"
set /P "UsersChoice=Type the number or letter of task you want, then press ENTER: "
rem Has the user really entered just one of the offered characters?
rem There must be nothing to process if the user has entered just 0
rem or 1 or 2. Otherwise the user's choice was either by mistake or
rem intentionally entered wrong. The string entered by the user is
rem referenced with delayed expansion to avoid an exit of batch
rem processing in case of user entered a syntax critical character.
for /F "tokens=1 delims=012" %%I in ("!UsersChoice!") do (
endlocal
goto MainMenu
)
rem Now it is safe to reference the variable value without usage of delayed
rem expansion as a syntax error caused by user input can't occur anymore.
rem The entered string does not contain any not expected character. But
rem it is possible that for example 11 was entered by mistake instead
rem of just 1. The entered string should have a length of 1 character.
if not "%UsersChoice:~1,1%" == "" (
endlocal
goto MainMenu
)
rem Exit this batch processing on user entered 0. Previous environment is
rem automatically restored by command processor by an implicit endlocal.
if "%UsersChoice%" == "0" exit /B
rem Restore previous environment as the called batch files are most
rem likely written for using standard command environment with delayed
rem expansion not enabled (exclamation mark interpreted different).
rem The current value of local environment variable must be passed
rem to previous environment for usage on GOTO command.
endlocal & goto Menu%UsersChoice%
:Menu1
call "%USERPROFILE%\Desktop\Menu1.bat"
goto MainMenu
:Menu2
call "%USERPROFILE%\Desktop\Menu2.bat"
goto MainMenu
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
cls /?
echo /?
endlocal /?
exit /?
for /?
goto /?
rem /?
set /?
setlocal /?
title /?
For meaning of & in line endlocal & goto Menu%UsersChoice% see answer on Single line with multiple commands using Windows batch file.
I tried your code and what I found was that when the input was 1 both :1 and :2 are executed but when the input is 2 only :2 is executed. To fix this you need to specify the end of :1 using Exit or another goto.
You might see that none the batches are being executed IF you do not put a pause in the end of your script. They would be executed but the result might just flash out of the screen.
Also I do not understand why have you used \\Menu1.batand not \Menu1.bat in
:1
call %userprofile%\desktop\\Menu1.bat
The final working code for me-
#echo off
:MENU
title MENU0
Echo 1 - Select Menu 1
Echo 2 - Select Menu 2
Echo 0 - Exit
Echo.
SET /P choice=Type the number or letter of task you want, then press ENTER:
IF %choice%==1 GOTO 1
IF %choice%==2 GOTO 2
IF %choice%==0 EXIT
:1
call yourpathhere\Menu1.bat
pause
GOTO cont
:2
call whatsoever\Menu2.bat
pause
GOTO cont
:cont
exit
That should fix your problem.
Hope I helped.
I may not be a pro, but I could help you!
I always add extra code on my games in order to avoid bugs, like this:
set /p letter=
if %letter% == 1 goto nocheck1
if %letter% == 2 goto nocheck2
if %letter% == 3 exit
:nocheck1
if %letter% == 1 goto saves
:nocheck2
if %letter% == 2 goto howtoplay
Maybe it could work on your problem!
I might have the code to do it:
#echo off
cls
:menu
cls
echo 1. Open Batch 1
echo 2. Open Batch 2
set /p test=Enter number here ----->
if %test% == 1 goto check1
if %test% == 2 goto check2
Edit the "Batch file name" text with your location of your batch file.
:check1
if %test% == 1 start C:\Users\%username%\Desktop\(batch file name).bat
:check2
if %test% == 2 start C:\Users\%username%\Desktop\(batch file name).bat
If there's still any errors with my code, let me know.
Hope this helps your problem!
Use cd to go to the location of batch file. For example:
rem myscript
echo calling batch file
cd demo\desktop\script
execute.bat
echo done
After the execution of that batch, control will return to the next line of your script.
Use "Start" instead of "Call" like so,
#echo off
:MENU
title MENU0
Echo 1 - Select Menu 1
Echo 2 - Select Menu 2
Echo 0 - Exit
Echo.
SET /P choice=Type the number or letter of task you want, then press ENTER:
IF %choice%==1 GOTO 1
IF %choice%==2 GOTO 2
IF %choice%==0 EXIT
:1
start %userprofile%\desktop\\Menu1.bat
:2
start %userprofile%\desktop\Menu2.bat
Try This:
#echo off
:MENU
title MENU0
Echo 1 - Select Menu 1
Echo 2 - Select Menu 2
Echo 0 - Exit
Echo.
SET /P choice=Type the number or letter of task you want, then press
Enter:
IF %choice%==1 GOTO 1
IF %choice%==2 GOTO 2
IF %choice%==0 EXIT
:1
cd users
cd %userprofile%
cd desktop
:: call Menu1.bat or use: start Menu1.bat
:: exit
:2
cd users
cd %userprofile%
cd desktop
:: call Menu2.bat or use: start Menu2.bat
:: exit
start "" C:\location\of\file\file.bat
This opens a new window, and as long as you have more commands to follow, the previous file that is calling the new one will still run along with this one.

Create a text file 1 by 1 and save it to directory

I have this command:
For /l %%n in (1,1,1) do echo welcome >> "C:\Users\Documents\Backup\TestingFile%%n.txt"
It creates a file and when you run it the next time it overwrites. It should create a file on each run.
For instance you run a script for two times it should 2 files but it does not.
Could anyone please help me?
Turns out you are asking the FOR command to count...
starting from one
stepping by one
ending at one.
So the FOR is doing what you asked it to, so getting just one file kind of makes sense. Let's ignore the file output part for a moment and see what the FOR is doing.
Here is an excerpt from the FOR command/s help text:
C:\tmp>for /?
...etc...
FOR /L %variable IN (start,step,end) DO command [command-parameters]
The set is a sequence of numbers from start to end, by step amount.
So (1,1,5) would generate the sequence 1 2 3 4 5 and (5,-1,1) would
generate the sequence (5 4 3 2 1)
Just for fun, let's skip the "write to a file part" and look at what the for loops are doing...
The original for loop is first with Welcome, then a slightly modified one with "more welcome"
Make sense?
C:\tmp>type foo.bat
echo off
For /l %%n in (1,1,1) do echo welcome, n=%%n
For /l %%n in (1,1,3) do echo ** more welcome, n=%%n **
C:\tmp>foo.bat
C:\tmp>echo off
welcome, n=1
** more welcome, n=1 **
** more welcome, n=2 **
** more welcome, n=3 **
C:\tmp>
If you want the batch file to create a new file each time it is run you will need to check for the existence of all the previous files first.
#echo off
set num=0
:LOOP
set /a num+=1
IF EXIST "C:\Users\Documents\Backup\TestingFile%num%.txt" GOTO LOOP
echo welcome >"C:\Users\Documents\Backup\TestingFile%num%.txt"
The flaw in this code though is that if you have 4 files created and someone deletes file 2 or 3, the next time it runs it will create that file instead of file 5.

Resources