Batch file IF statement only using first character - batch-file

Not quite sure what I'm doing wrong. For the most part, this works. If I were to type just 1, I would go to opt1.
The problem is, if I type "11", "1111", or even "1234567" it always goes to opt1. The only time it seems to not select opt1 is when the first number is something other than 1.
Likewise, entering 21 chooses option 2. The only way I've been able to get this to work as intended, which is only entering 1, 2, or 3 selects the respective options, is to omit the IF NOT statement.
Could someone kindly point me in the right direction?
#ECHO OFF
CLS
:MAIN_MENU
ECHO Welcome Menu
ECHO.
ECHO 1 - Option 1
ECHO 2 - Option 2
ECHO 3 - Option 3
ECHO.
SET ans=
SET /P ans="Select your option and then press ENTER: "
IF NOT "%ans%" == "" SET ans=%ans:~0,1%
IF "%ans%" == "1" GOTO opt1
IF "%ans%" == "2" GOTO opt2
IF "%ans%" == "3" GOTO opt3
ECHO "%ans%" is not a valid option, please try again!
ECHO.
PAUSE
CLS
GOTO MAIN_MENU
:opt1
ECHO This is option 1
PAUSE
CLS
GOTO MAIN_MENU
:opt2
ECHO This is option 2
PAUSE
CLS
GOTO MAIN_MENU
:opt3
ECHO This is option 3
PAUSE
CLS
GOTO MAIN_MENU

With the code you snipped I can't replicate the bug, however, I do remember to face that very same problem long time ago.
The answer is the quotes; just add it and you will avoid more complex code:
:input
cls
set ans=:
set /p ans=
if "%ans%" equ "1" (
goto opt1
) else (
goto input
)
:opt1
echo success!
EDIT: Regarding the first ans that was set, it is to clean the shell memory. Sometimes a variable could be stored in Windows memory, and even if you do not input anything to the set /p variable, and only press return, the batch will check for the variable and it will already have a value previously set in the memory. Example:
set /p option=
The user input "1". As a result, Windows will store option=1, or, %option% resulting in 1.
So, the even if you do not input anything, the next code will move forward as the answer is previously stored in the memory:
set /p option=
The user does NOT input anything, only press return. The code will move on:
if "%option%" equ "1" do (
echo %option% is equal to 1 because it was previously stored.
)
EDIT: Here is the code, with comments and explanations:
#echo off
:main_menu
cls
echo Welcome menu
echo.
echo 1 - option 1
echo 2 - option 2
echo 3 - option 3
echo.
rem Blank "ans" will clean the memory for a previous set value.
set ans=
rem You can either quote the whole variable with its option, ot not quote it at all.
rem However, its always better to quote it, as follows.
set /p "ans=select your option and then press enter:"
if "%ans%" == "1" goto opt1
if "%ans%" == "2" goto opt2
if "%ans%" == "3" goto opt3
rem The following line will force a loop to main menu if only return is pressed; blank options will not display message.
if "%ans%" == "" goto main_menu
rem In case that another option rather than 1, 2 or 3 are pressed, the loop will warn you, and then return to main menu.
echo "%ans%" is not a valid option, press any key to try again!
pause > nul
goto main_menu
:opt1
cls
echo this is option 1
pause
goto main_menu
:opt2
cls
echo this is option 2
pause
goto main_menu
:opt3
cls
echo this is option 3
pause
goto main_menu
Regarding the %ans:~0,1%, it is to limit the string to a certain position.
So, for example, %any_variable:~0,5% is saying "Start the string since character 0, and go ahead until character 5". You can try that out in the following example. Notice that all echo lines will type out the very same text:
#echo off
set example=Batch files are kinda cool
echo %example%
echo %example:~0,11% are kinda cool
echo Batch files %example:~12%
pause

As it turns out, there were remnants in the code that needed to be removed.
IF NOT "%ans%" == "" SET ans=%ans:~0,1%
IF "%ans%" == "1" GOTO opt1
I'm not entirely sure what that first line was setting however, removing it resolved the issue.
Thanks for all the help, much appreciated!

Related

Batch Coding Menu Option to Go Back

I'm fairly new to coding, and I've been told to start with batch files. I'm attempting to make a text based game that prompts the user to choose between a few options to progress through the story. I've got the basic idea down, but I ran into some trouble with making a menu. I've done some research on here, and have searched other sites, but can't seem to make heads or tails of some of the answers to similar questions. Most of the answers write out code that I assume would work, but I need to know the WHY behind these answers, and I haven't really found any answers that I could understand.
TLDR; I need to make a menu for a text based game, that allows the user to return the label they left off on.
What I have so far:
:MainMenu
cls
echo Input Options:
echo.
echo ::1) View Storyline Changes
echo ::2) Restart Test
echo ::3) Resume Test
echo ::4) Help
echo ::5) Quit
echo.
set /p input=Input:
if "%input%" == "1" goto StorylineChanges
if "%input%" == "2" goto Rst
if "%input%" == "3" goto ResumeTest
if "%input%" == "4" goto HelpScrn
if "%input%" == "5" exit
:StorylineChanges
cls
echo Unimportant to test.
echo.
echo Input "m" to go back
echo.
set /p input=Input:
if "%input%" == "m" goto Main Menu
if "%input%" == " " goto WrongInputStorylineChanges
:Rst
cls
goto :StartTest
echo off
:ResumeTest
cls
REM ***THIS IS WHERE I NEED HELP ***
pause >nul
goto StartTest
As you can probably immediately tell, I BARELY have a grasp on basic commands, so please keep that in mind if you provide an answer. I'd really appreciate any help you guys could give me. Thanks so much.
I cannot unravel the spaghetti code, but I can give an example
detailing how to go back to the menu as the title asks.
#echo off
:MainMenu
cls
echo Input Options:
echo.
echo ::1) View Storyline Changes
echo ::2) Restart Test
echo ::3) Resume Test
echo ::4) Help
echo ::5) Quit
echo.
set /p input=Input:
if "%input%" == "1" call :StorylineChanges
if "%input%" == "2" call :Rst
if "%input%" == "3" call :ResumeTest
if "%input%" == "4" call :HelpScrn
if "%input%" == "5" exit /b 0
goto :MainMenu
:StorylineChanges
echo Use "goto :eof" to exit script or exit called label.
pause
goto :eof
:Rst
echo Use "exit /b" to exit script or exit called label with a errorlevel.
pause
exit /b 0
:ResumeTest
>&2 echo Exit called label with errorlevel 1. This line is to stderr.
pause
exit /b 1
:HelpScrn
echo Help. Exit with implicit 0.
pause
exit /b
The above uses call to access each label. Exit of a called label
returns back to the point of the call. The menu is in a loop so it keeps
showing until you input 5 to exit the script.
I added pauses into the labels so you could see the messages before clr
is called.

Batch crashes with spaces even with var set and delayed expansion

I just started coding two days ago. (It's oddly addictive). And I started so that I could make a simulated "computer hacking" experience as a portion of an escape room that I am designing. Mainly, I have just been looking around and finding different ideas and putting them together in an aesthetically pleasing way. However, I want to make it crash resistant. So that when people are using it they don't get booted for just button mashing and pressing enter.
I got this to work in the :menu but not on the faux log in page.
Below is the code that I wrote that I want to be able to work on other pages:
:menu
cls
set "answer=Nothing^!"
set var=%var: =%
echo.
echo Menu
echo.
echo 1. Login
echo 2. Instructions
echo 3. Exit
echo.
set /p answer=Type the number of your option and press enter:
echo.
echo.
if /I "!answer!" == "exit" goto exit
echo You answered: %answer%
echo Which is not a valid entry.
echo Try again.
if /I %answer% == 1 goto :Login1
if /I %answer% == 2 goto :Instructions
if /I %answer% == 3 goto :Exit
if /I %answer% == 43153 goto :done
pause
goto :menu
Here is the code I cannot get to work.
:Login2
cls
set "un=Nothing^!"
set "pw=Nothing^!"
set var=%var: =%
echo.
echo Log On
echo.
if %counter% lss 5 echo Password incorrect, %counter% attempts left
echo.
echo.
set /p un=Enter your UserID:
set /p pw=Enter your Password:
if /I %un% == ID (
if /I %pw% == PASSWORD goto :loading1
)
if /I !un! == "exit" (
if !pw! == "exit" goto loading2
goto :loading2
If I type something random to input such as: asdf asdf
The menu doesn't crash. But the login2 page does. It crashes if it is username and password OR just username OR just password that have spaces. And if I just "enter" through the screen it does not auto-populate " Nothing^! " like the menu does.
I would paste the entirety of the file below, but because with the decorative liberties I took it won't fit well on this page. And I can't find a place to upload it. But any comments or suggestions would be greatly appreciated.
Again, thank you for any help!
if /I "!answer!" == "exit" goto exit
is correct
if /I %un% == ID (
is syntactically correct, provided un contains a simple string not containing spaces.
if un contains some spaces then the command is interpreted as
if /I some spaces == ID (
and the required syntax is
if [/i] string1 operator string2 dothis
An operator like == is also a string, so cmd sees spaces where it's expecting an operator, so it protests.
To allow spaces (and other separators) in a string, "quote the string" as you did with the first if above.
Oh - and it's particular about the quotes - they must exactly match - you can't quote one side and not the other.
This applies to string arguments only - where the arguments are numerics or resolve to a numeric, the quotes are not used. If they are used with numeric arguments, the arguments will be compared alphabetically so 98 is greater than 123 because 9 is greater than 1.
Always enquote variables in your IF expressions.
IF /i "%un%" == "ID" ...
IF /i "%pw%" == "PASSWORD" ...
or even better use delayed expansion here
IF /i "!un!" == "ID" ...
IF /i "!pw!" == "PASSWORD" ...

How to use goto command in if choice?

I am running the following program ,
#echo off
color 0a
cls
:MENU
echo What do you want to do ?
echo.
echo 1- Flash
echo 2- Wipe
echo 3- Check
echo 4- Go Back
echo.
set /p choice=
if %choice%==1 goto 1
if %choice%==2 goto 2
if %choice%==3 goto 3
if %choice%==4 goto 4
echo Invalid Choice
goto MENU
:1
flash.bat
:2
wipe.bat
:3
check.bat
:4
back.bat
In this program when i press any other key other than 1,2,3,4 it need to show invalid choice. But, its not working.. its shows error "goto command was unexpected at this time".
Please help me guys..When pressing anyother key it need to show invalid choice. Pls help guys...
I suggest, using choice, which does errorhandling on it's own, so you don't have to deal with that. There are many ways (many possible inputs) to break your script when using set /p.
If you want to keep with set /p, at least preset the variable (set /p doesn't set the variable to "empty" when you press ENTER, but lets it unchanged):
set choice=4
set /p choice=
echo %choice%
...
Additional bonus: you have a default action.

My batch file skips specific loops

My batch file skips specific loops and just does certain loops (it only does the first three loops and ignores the rest).
I tried rewriting the batch file, incorporating the new code into an old existing batch file I wrote, but I can't get it working.
echo 1. Login
echo 2. Exit
echo.
set /P M = Command :
IF M == 1 GOTO 1
:1
cls
echo Login
echo.
Set Pass1 = MCTh3sn3r
Set /P Pass = Enter Password :
IF Pass == %Pass1% GOTO 2
:2
cls
echo.
echo Login Successful GOTO 4
:3
cls
echo.
echo Incorrect Password
:4
echo.
echo 1. Shutdown (S)
echo 2. Reboot (R)
echo 3. Logoff (L)
echo 4. Task Manager (TM)
echo 5. Command Prompt (CP)
echo 6. File Locker (FL)
echo. Set /P Choice = Command :
IF Choice == "S" GOTO 5
IF Choice == "R" GOTO 6
IF Choice == "L" GOTO 7
IF Choice == "TM" GOTO 8
IF Choice == "CP" GOTO 9
IF Choice == "FL" GOTO 10
:5
cls
echo.
echo System will now shutdown
Timeout /t 5
Shutdown /s
GOTO End
:6
cls
echo.
echo System will now reboot
timeout /t 5
Shutdown /r
GOTO End
:7
cls
echo.
echo System will now logoff
timeout /t 5
Logoff
GOTO End
:8
gpupdate /force
gpupdate /force
gpupdate /force
gpupdate /force
start taskmgr
GOTO End
:9
gpupdate /force
gpupdate /force
gpupdate /force
gpupdate /force
start cmd
GOTO End
:10
(
if EXIST "PrivateFolder" goto
11
if NOT EXIST Locker goto 12
:13
echo Are you sure you want to
lock the folder (Y/N) ?
set /p Choice = Command :
IF Choice == "Y" goto 14
IF Choice == "y" goto 14
IF Choice == "N" goto 15
IF Choice == "n" goto 15
echo Invalid Choice goto 13
:16
ren Locker "PrivateFolder"
attrib +h + s "PrivateFolder"
echo Folder Locked GOTO End
:11
echo Enter password to unlock
file :
set /p Pass = Password :
IF NOT %Pass% == MCTh3sn3r goto
17
attrib -h -s "PrivateFolder"
ren "PrivateFolder" Locker
echo File locked successfully.
GOTO End
:17
echo Invalid password.
GOTO End
:12
md Locker
echo Locker created
successfully.
GOTO End
)
:End
Exit
Well lets start at the TOP.
This set of code has three things wrong with it.
Do not leave a space between your variable names and variable assignments.
When you need to use a variable you need to surround it with percent symbols.
Your GOTO command will GOTO label 1 regardless of the variable M equaling 1.
.
echo 1. Login
echo 2. Exit
echo.
set /P M = Command :
IF M == 1 GOTO 1
:1
This code should really look something like this.
echo 1. Login
echo 2. Exit
echo.
set /P M=Command :
IF "%M%"=="1" (
GOTO 1
) else (
GOTO END
)
:1
You make the same mistakes in the next set of code. Not sure why you chose to use the percent symbols for one variable but not the other. Again, you need to close up the spaces, use percent symbols for all your variables and your GOTO will go to the label 2 regardless so you need some other code to branch to.
cls
echo Login
echo.
Set Pass1 = MCTh3sn3r
Set /P Pass = Enter Password :
IF Pass == %Pass1% GOTO 2
:2
So again, using my best coding practices I would code it like this.
:1
cls
echo Login
echo.
Set Pass1=MCTh3sn3r
Set /P Pass=Enter Password :
IF "%Pass%"=="%Pass1%" (
GOTO 2
) else (
Echo Wrong Password
Pause
GOTO 1
)
Just going to keep repeating myself. Same problems. Close up the spaces and use percent symbols with your variables. Might want to throw in a case insensitive check for their choices on this one. Not sure how you thought their answers were ever going to match here. You have quotes surrounding one side of your comparison but not the other. Not even going to correct this code you should understand by now what you are doing wrong.
echo. Set /P Choice = Command :
IF Choice == "S" GOTO 5
IF Choice == "R" GOTO 6
IF Choice == "L" GOTO 7
IF Choice == "TM" GOTO 8
IF Choice == "CP" GOTO 9
IF Choice == "FL" GOTO 10
No clue why you are using parentheses here.
:10
(
And here.
)
:End
Exit
This one is dead obvious. You can't have your label on another line.
if EXIST "PrivateFolder" goto
11
And here again. Close up the spaces. Put quotes on both sides of your comparisons. Use percent symbols to reference a variable. And read the HELP for the IF command. Use the /I option!
:13
echo Are you sure you want to
lock the folder (Y/N) ?
set /p Choice = Command :
IF Choice == "Y" goto 14
IF Choice == "y" goto 14
IF Choice == "N" goto 15
IF Choice == "n" goto 15
echo Invalid Choice goto 13
While we are here I would advise that if you are going to keep using the same variable over and over and over again that you clear out the variable before you ask the question. Make this change above.
set "Choice="
set /p Choice=Command :
Couple of problems here. The word file: is on its own line. The number 17 is on its own line. You finally realized that you needed to use percent symbols for you variables but the variable %Pass% is not the same as the variable %Pass %. Close up the spaces and use quotes.
echo Enter password to unlock
file :
set /p Pass = Password :
IF NOT %Pass% == MCTh3sn3r goto
17

Error: 1 was unexpected at this time

So I'm making a game based on making decisions using notepad ++ and batch. I'm new to this and I have no idea what the problem is here.
:start
;startup
cls
echo Wine or Cheese?
echo.
echo 1. Wine
echo 2. Cheese
echo 3. Exit
echo.
set /p input0=Enter:
if %input0% equ 1 goto winestart
if %input0% equ 2 goto cheese
if %input0% equ 3 goto exit
When I select winestart or 1, it goes to winestart for a splitsecond then crashes, with the error message: 1 was unexpected at this time.
Winestart looks like this:
:winestart
cls
echo You are alone. You have a bottle of wine and the clothes you are wearing.
echo What kind of wine do you have?
echo.
echo 1. Red Wine
echo 2. White Wine
set p/ input7=Enter:
if %input7% equ 1 goto redwine
if %input7% equ 2 goto whitewine
/p indicates that the variable is simply set by user input. –
SET
:winestart
cls
echo You are alone. You have a bottle of wine and the clothes you are wearing.
echo What kind of wine do you have?
echo.
echo 1. Red Wine
echo 2. White Wine
set /p input7=Enter:
if %input7% equ 1 goto redwine
if %input7% equ 2 goto whitewine
[Edit: Correct cure, but no explanation of why the error message appears]
Since input7 is not entered, the if statement is interpreted as
if equ 1 goto redwine
cmd expects if something equ anotherthing dosomething so it sees 1 as the comparison-operator. This is not one of the operators it recognises, so it responds that the 1 is unexpected.
A better form of this is
if /i "%input7%" equ "1" goto redwine
where the /i forces a case-insensitive comparison and "quoting the arguments" preserves the syntax requirement where the user enters nothing or a string containing spaces (you have no control over the user's response.)

Resources