Checking input via a batch file - batch-file

I am doing user input and checking to see if they typed n or y... and it's not working because it says both either way.
Here's what I have:
#echo off
set /P theuserinput="Type your name: "
echo So your name is: %theuserinput%?
set /P isit="Y/N: "
echo You typed: %isit%
if (%isit% == "y") goto :saidyes
if (%isit% == "n") goto :saidno
:saidyes
echo Hooray!
:saidno
echo Aww
PAUSE

First you can add a default goto after the two if's.
Then, in both tests you have to add the quotes around %isit% and to remove the parenthesis. You may also add the /I flag to do an insensitive string comparison.
Finally, add goto after each echo to jump over the next one.
#echo off
set /P theuserinput="Type your name: "
echo So your name is: %theuserinput%?
set /P isit="Y/N: "
echo You typed: %isit%
if /I "%isit%" == "Y" goto :saidyes
if /I "%isit%" == "N" goto :saidno
goto :error
:saidyes
echo Hooray!
goto :end
:saidno
echo Aww
goto :end
:error
echo ERROR
:end
PAUSE

Need change in syntax
Here is the modified code
#echo off
set /P theuserinput="Type your name: "
echo So your name is: %theuserinput%?
set /P isit="Y/N: "
echo You typed: %isit%
if "%isit%" == "Y" GOTO saidyes
if "%isit%" == "N" GOTO saidno
:saidyes
echo Hooray!
GOTO paused
:saidno
echo Aww
:paused
PAUSE
....
In above example The Y/N is supposed to be capital letter only.

There are a few things I would do differently to this to ensure that it works properly...
First off the corrected code is the following, but at the bottom is my suggested code:
#echo off
setlocal
set theuserinput=
set /P theuserinput="Type your name: "
echo So your name is: %theuserinput%?
set /P isit="Y/N: "
echo You typed: %isit%
if '%isit%'== 'Y' goto saidyes
if '%isit%'=='N' goto saidno
:saidyes
echo Hooray!
goto end
:saidno
echo Aww
goto end
:end
pause
endlocal
exit
However, to make sure that you only get Y or N there are a few things I would put in...
First I would make sure that you only grab the first letter by adding:
IF NOT '%isit%'=='' set isit=%isit:~0,1%
Next I would make sure that you only have Capital letters, so you make the swap if they are lowercase, because this will actually not work in some cases if the CaSe isn't correct:
if '%isit%'== 'y' set isit=Y
if '%isit%'== 'Y' goto :saidyes
if '%isit%'=='n' set isit=N
if '%isit%'=='N' goto :saidno
The final edit for this file could look like the following:
#echo off
:top
set theuserinput=
set /P theuserinput="Type your name: "
echo So your name is: %theuserinput%?
set /P isit="Y/N: "
IF NOT '%isit%'=='' set isit=%isit:~0,1%
IF '%isit%'=='y' set isit=Y
IF '%isit%'=='Y' goto saidyes
IF '%isit%'=='n' set isit=N
IF '%isit%'=='N' goto saidno
goto top
:saidyes
echo You typed: %isit%
echo Hooray!
goto end
:saidno
echo You typed: %isit%
echo Aww
goto end
:end
pause
exit

Quotes are commonly misused in DOS batch files. Unlike UNIX shell scripts, the DOS batch language is not thought-out. For example, when the isit variable contains quotes
set isit="Y"
then the above if-statements expand to
IF ""Y"" == "Y" GOTO saidyes
IF ""Y"" == "N" GOTO saidno
because cmd.exe does not remove the quotes in "%isit%"=="Y" before evaluating the expression.
Quotes in isit shall not occur with the original batch file posted here. But often you process path names in batch files, and Windows passes long file names in quotes to hide blanks. For example, as in "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC". To work around this it is common practice to write if-statements so:
IF ["%isit%"] == ["Y"] GOTO saidyes
IF [%isit%] == ["Y"] GOTO saidyes
IF [%isit%] == [Y] GOTO saidyes
For set isit="Y" this becomes:
IF [""Y""] == ["Y"] GOTO saidyes
IF ["Y"] == ["Y"] GOTO saidyes
IF ["Y"] == [Y] GOTO saidyes
and for set isit=Y:
IF ["Y"] == ["Y"] GOTO saidyes
IF [Y] == ["Y"] GOTO saidyes
IF [Y] == [Y] GOTO saidyes
and for set isit=:
IF [""] == ["Y"] GOTO saidyes
IF [] == ["Y"] GOTO saidyes
IF [] == [Y] GOTO saidyes
which is far from being elegant, but at least works now for quoted and unquoted variables. It also works when isit is empty. Oftenly batch files stop because of empty variables:
set x=
REM ...
IF %x% == x GOTO x
because now the if-statement expands to:
IF == x GOTO x
and cmd.exe fails. These errors are usually hard to debug.
The trick is very old; I remember using it already in MSDOS. Note that the square brackets are not evaluated by cmd.exe; they're just some rarely used characters. But it's just a trick. Any advanced batch script needs a dequoting-function:
#echo off
setlocal EnableExtensions
setlocal EnableDelayedExpansion
REM ...
set /P isit="Y/N: "
call :dequote isit
REM ...
IF "!isit!" == "Y" GOTO saidyes
IF "!isit!" == "N" GOTO saidno
REM ...
goto done
:dequote
for /f "delims=" %%A in ('echo %%%1%%') do set %1=%%~A
goto :eof
:done
The deqote-subroutine removes any double quotes around the variable name passed to the function.
After dequoting the []-trick is not required anymore. Note also the use of ! instead of %. The exclamation marks force cmd.exe to reexpand isit.

I changed the code somewhat to help fix your problem. Instead of goto :(function) you just say goto (function)
#echo off
set /P theuserinput=Type your name:
echo So your name is: %theuserinput%?
set /p isit=Y/N:
echo You typed: %isit%
if %isit% == "y" goto saidyes
if %isit% == "n" goto saidno
:saidyes
echo Hooray!
:saidno
echo Aww
pause

Related

There is an issue with my batch file code, can't find the problem

So I'm making a very ambitious game using batch to challenge myself. I've been working on the "shop" segment of this game but for some reason when I enter 'b' or 'B' it doesn't send me back to the menu, but reads it as I wanted to buy a medkit and sends me to the "medkit purchased" line of code. I've tried to add pause >nul and pause between the shop line of code and the purchased line of code, but it didn't help. I also tried double checking to see if I typed menu right many times. There has to be something I'm missing, help appreciated, I've been messing with it for almost 2 hours now.
Edit: I have not entered the other events yet, only medkit and go back to menu.
Edit2: I've added some more variables and instead of taking me to them it takes me to the medkit code again.
Edit: I removed the percents, you guys can stop bugging me bout it. The issue still is not fixed and I do not have choice.exe so choice commands don't work.
Here is the code:
:shop
cls
echo Welcome to the shop!
echo Money: $%money%
echo.
echo 1. Buy Med Kit -$30
echo 2. Buy Shotgun Ammo (1) -$15
echo 3. Buy Assult Rifle Ammo (5) -$20
echo 4. Buy Missle (1) -$50
echo 5. View Armor
echo 6. View Modifiers
echo.
echo Enter 'B' to go back.
echo.
set /p %shopOp%=
if '%shopOp%' == '1' goto medkit1
if '%shopOp%' == '2' goto sg1
if '%shopOp%' == '3' goto ar1
if '%shopOp%' == '4' goto rpg1
if '%shopOp%' == '5' goto armors1
if '%shopOp%' == '6' goto mods1
if '%shopOp%' == 'B' goto menu
if '%shopOp%' == 'b' goto menu
:medkit1
cls
set /a money=%money%-30
if %money% LSS 0 goto noBuy1
set /a medK=%medK%+1
echo You bought 1 medkit for $30!
echo You now have %medK% med kits now!
echo.
echo Press enter to continue
pause >nul
goto shop
:noBuy1
cls
set /a money=%money%+30
echo You dont have enough money!
echo You have $%money%. You need $30.
echo.
echo Press enter to continue
pause >nul
goto shop
Okay so you don't have choice. How about xcopy?
A version adapted from the link in my comment that substitutes the choice utility with xcopy to return keypress:
#Echo off
Set Echo.ID=Call :ID.Label "%%~1" "%%~2"
Setlocal EnableDelayedExpansion
Title Menu Navigation Example
:Bar
Set "Left.Date="
IF /I "!Left.Bar!" == "Yes" Goto :Date
Call :[+Menu] "Bar" "Drink Fight Chat Leave"
Goto :Bar
:Date
Set "Left.Bar="
IF /I "!Left.Date!" == "Yes" Goto :Bar
Call :[+Menu] "Date" "Dinner Flirt Leave"
Goto :Date
:[+Menu] <Location / Core Menu option> <Sub Actions / Menu Items as list>
::: - Build menu and choice list for display
CLS
Set "CHOICES="
Set "Actions="
For %%A in (%~2) Do (
Set "Option=%%~A"
Set Actions=!Actions! "%%~A"
Set CHOICES=!CHOICES! "!Option:~0,1!"
Set "Option=[!Option:~0,1!]!Option:~1,100!"
Echo !Option!
)
::: - Return key literal from xcopy command and call relevent menu item with Identifying Params
Set "Option="
Set Key=
For /F "Delims=" %%A in ('xcopy /w "%~f0" "%~f0" 2^>nul') do (
If Not Defined Key Set "Key=%%A"
)
Set "Key=!Key:~-1!"
::: - Restrict keypress to available options, fall through to 'Goto :[Menu]' when no Call is made (Invalid keypress)
For %%O in (%~2) Do (
Set "Option=%%~O"
Set "Option=!Option:~0,1!"
If /I "!Option!" == "!Key!" Call :[%~1_%%~O-!Key!] "%%~1 %%~O" "%~1"
)
Goto :[+Menu]
:[Bar_Drink-D]
%Echo.ID%
Goto :!Loc!
:[Bar_Fight-F]
%Echo.ID%
Goto :!Loc!
:[Bar_Chat-C]
%Echo.ID%
Goto :!Loc!
:[Bar_Leave-L]
%Echo.ID%
Set "Left.Bar=Yes"
Goto :!Loc!
:[Date_Dinner-D]
%Echo.ID%
Goto :!Loc!
:[Date_Flirt-F]
%Echo.ID%
Goto :!Loc!
:[Date_Leave-L]
Set "Left.Date=Yes"
%Echo.ID%
Goto :!Loc!
:ID.Label <%~1> <%~2>
Title %~1
::: - Identify return Label
Set "Loc=%~2"
Exit /B

Goto was unexpected time

When I run the script Console prints goto was unexpected time, (I have bad English)
#echo on
set versiyon=0.1
if %komut1%=="metin" goto metinapi
if %komut1%=="internet" goto internetapi
if %komut1%=="dosya" goto dosyaapi
if %komut1%=="sistem" goto sistem
if %komut1%=="versiyon"(
echo %versiyon%
pause
)
color c
echo Hata:Aranan sey bulunamadi!Aradiginiz seyi dogru yazdiginizdan emin
olun!ya da frameworku guncelleyin. suanki verisyon:%versiyon% KOD:1
pause
:metinapi
if %komut2%=="degistir"(
if %komut3%=="" goto null
if %komut4%=="" goto null
if %komut5%=="" goto null
setlocal ENABLEDELAYEDEXPANSION
set str=%komut3%
set str=%str:!komut5!=!komut4!%
echo %str%
pause
)
if %komut2%=="bul"(
if %komut3%=="" goto null
if %komut4%=="" goto null
Echo.%komut3%| findstr /C:%komut4%>nul && (Echo.EVET) || (Echo.HAYIR)
pause
)
:null
color c
echo Deger null olamaz!KOD:2
pause
You can say why komuts are empty beacause I want user input them like api.bat set komut1=metin set komut2=bul ...
You haven't declared %komut1%, and therefore the if command failed as well. And if the command if executed (right at the line #3), then it would be:
if =="metin" goto metinapi
^
Error here, because "%komut1%" is equal to ""
To fix this, you may have to include double quotes " before and after %komut1%:
if "%komut1"=="metin" goto metinapi
Now not only that, but you may have to edit more commands in order to make it working, like after you fix line #3, you'll have to fix line #4 and #5, etc...

Batch -"access is denied" when accessing a text file using batch

I have been having problems with making a batch script that can write into a old text file. When i try to run it with the old text file it says that "access is denied" (so when i try to put any text into the existing file)
Anyways here is the code:
#echo off
title file editor/creator
set lineNR=0
:start
set /p ANS= Do you want to access a 1:"old file" or 2"create a new" [1/2]
if %ANS% EQU 1 ( goto old
) ELSE if %ANS% EQU 2 ( goto new
) ElSE ( echo invalid input & goto start)
:old
set /p name = what is the name of the file
set /p ending = what type of file is it
goto loop
:new
set /p name= what do you want the name of the file to be
set /p ending= what type of file do you want the file to be
echo %name%.%ending%
:Q1
set /p echo_off= do you want echo to be off? [y/n]
if %echo_off% EQU y (
echo #echo off >%name%.%ending%
goto loop
) ELSE IF %echo_off% EQU n (
goto loop
) ELSE (
goto Q1
)
:loop
echo press CTRL+LSHIF+C to end loop
goto loop1
:loop1
set /a lineNR=%lineNR% + 1
set /p line= %lineNR%:
echo %line% >>%name%.%ending%
// this is where it says that access is denied
goto loop1
It is just a simple, but a common issue.
set a = b
Creates a variable named a (with the space) and a value of b(with the space).
Remove the spaces and it will work.

Batch-file wrong input fix?

#echo off
:start
cls
color e
echo YOU HAVE WON $1,000,000! WHAT WILL YOU DO?
echo.
echo =================
echo -Take it (1)
echo -Leave it (2)
echo -Double it (3)
echo =================
echo.
set /p INPUT=Please specify your answer:
If /i "%INPUT%" == "1" goto 1
If /i "%INPUT%" == "2" goto 2
If /i "%INPUT%" == "3" goto 3
If /i "%INPUT%" == "Jonah" goto Jonah
If /i "%INPUT%" == "" goto Wrong
I have a strange problem. Above is a code and for some reason, when I type in "INPUT" something like 'Aiden' it would think it meant '1'. Is there a way to make every wrong answer goto wrong. (Wrong answers like Aiden which isn't even specified there. But not only Aiden, any other thing).
After your if statements you need to put a catch-all GOTO statement so if none of the others work, it will go to wrong instead of just continuing into the block right below
#echo off
:start
cls
color e
echo YOU HAVE WON $1,000,000! WHAT WILL YOU DO?
echo.
echo =================
echo -Take it (1)
echo -Leave it (2)
echo -Double it (3)
echo =================
echo.
set /p INPUT=Please specify your answer:
If /i "%INPUT%" == "1" goto 1
If /i "%INPUT%" == "2" goto 2
If /i "%INPUT%" == "3" goto 3
If /i "%INPUT%" == "Jonah" goto Jonah
goto Wrong

Switch statement equivalent in Windows batch file

I wonder if there is a simple way to branch execution in a Windows batch file depending on the value of one single expression. Something akin to switch/case blocks in C, C++, C#, Java, JavaScript, PHP, and other real programming languages.
My only workaround is a plain if/else block where the same expression is repeatedly checked for equality against different values:
IF "%ID%"=="0" (
REM do something
) ELSE IF "%ID%"=="1" (
REM do something else
) ELSE IF "%ID%"=="2" (
REM do another thing
) ELSE (
REM default case...
)
So dumb. Is there a better solution?
I ended up using label names containing the values for the case expressions as suggested by AjV Jsy. Anyway, I use CALL instead of GOTO to jump into the correct case block and GOTO :EOF to jump back. The following sample code is a complete batch script illustrating the idea.
#ECHO OFF
SET /P COLOR="Choose a background color (type red, blue or black): "
2>NUL CALL :CASE_%COLOR% # jump to :CASE_red, :CASE_blue, etc.
IF ERRORLEVEL 1 CALL :DEFAULT_CASE # If label doesn't exist
ECHO Done.
EXIT /B
:CASE_red
COLOR CF
GOTO END_CASE
:CASE_blue
COLOR 9F
GOTO END_CASE
:CASE_black
COLOR 0F
GOTO END_CASE
:DEFAULT_CASE
ECHO Unknown color "%COLOR%"
GOTO END_CASE
:END_CASE
VER > NUL # reset ERRORLEVEL
GOTO :EOF # return from CALL
This is simpler to read:
IF "%ID%"=="0" REM do something
IF "%ID%"=="1" REM do something else
IF "%ID%"=="2" REM do another thing
IF %ID% GTR 2 REM default case...
Compact form for short commands (no 'echo'):
IF "%ID%"=="0" ( ... & ... & ... ) ELSE ^
IF "%ID%"=="1" ( ... ) ELSE ^
IF "%ID%"=="2" ( ... ) ELSE ^
REM default case...
After ^ must be an immediate line end, no spaces.
I guess all other options would be more cryptic. For those who like readable and non-cryptic code:
IF "%ID%"=="0" (
REM do something
) ELSE IF "%ID%"=="1" (
REM do something else
) ELSE IF "%ID%"=="2" (
REM do another thing
) ELSE (
REM default case...
)
It's like an anecdote:
Magician: Put the egg under the hat, do the magic passes ... Remove the hat and ... get the same egg but in the side view ...
The IF ELSE solution isn't that bad. It's almost as good as python's if elif else. More cryptic 'eggs' can be found here.
I searched switch / case in batch files today and stumbled upon this. I used this solution and extended it with a goto exit.
IF "%1"=="red" echo "one selected" & goto exit
IF "%1"=="two" echo "two selected" & goto exit
...
echo "Options: [one | two | ...]
:exit
Which brings in the default state (echo line) and no extra if's when the choice is found.
Hariprasad didupe suggested a solution provided by Batchography, but it could be improved a bit. Unlike with other cases getting into default case will set ERRORLEVEL to 1 and, if that is not desired, you should manually set ERRORLEVEL to 0:
goto :switch-case-N-%N% 2>nul || (
rem Default case
rem Manually set ERRORLEVEL to 0
type nul>nul
echo Something else
)
...
The readability could be improved for the price of a call overhead:
call:Switch SwitchLabel %N% || (
:SwitchLabel-1
echo One
goto:EOF
:SwitchLabel-2
echo Two
goto:EOF
:SwitchLabel-3
echo Three
goto:EOF
:SwitchLabel-
echo Default case
)
:Switch
goto:%1-%2 2>nul || (
type nul>nul
goto:%1-
)
exit /b
Few things to note:
As stated before, this has a call overhead;
Default case is required. If no action is needed put rem inside to
avoid parenthesis error;
All cases except the default one are executed in the sub-context. If
you want to exit parent context (usually script) you may use this;
Default case is executed in a parent context, so it cannot be
combined with other cases (as reaching goto:EOF will exit parent
context). This could be circumvented by replacing goto:%1- in
subroutine with call:%1- for the price of additional call overhead;
Subroutine takes label prefix (sans hyphen) and control variable. Without label
prefix switch will look for labels with :- prefix (which are valid) and
not passing a control variable will lead to default case.
Try by this way. To perform some list of operations like
Switch case has been used.
Checking the conditional statements.
Invoking the function with more than two arguments.
#echo off
:Start2
cls
goto Start
:Start
echo --------------------------------------
echo Welcome to the Shortcut tool
echo --------------------------------------
echo Choose from the list given below:
echo [1] 2017
echo [2] 2018
echo [3] Task
set /a one=1
set /a two=2
set /a three=3
set /a four=4
set input=
set /p input= Enter your choice:
if %input% equ %one% goto Z if NOT goto Start2
if %input% equ %two% goto X if NOT goto Start2
if %input% equ %three% goto C if NOT goto Start2
if %input% geq %four% goto N
:Z
cls
echo You have selected year : 2017
set year=2017
echo %year%
call:branches year
pause
exit
:X
cls
echo You have selected year : 2018
set year=2018
echo %year%
call:branches year
pause
exit
:C
cls
echo You have selected Task
call:Task
pause
exit
:N
cls
echo Invalid Selection! Try again
pause
goto :start2
:branches
cls
echo Choose from the list of Branches given below:
echo [1] January
echo [2] Feburary
echo [3] March
SETLOCAL
set /a "Number1=%~1"
set input=
set /p input= Enter your choice:
set /a b=0
set /a bd=3
set /a bdd=4
if %input% equ %b% goto N
if %input% leq %bd% call:Z1 Number1,input if NOT goto Start2
if %input% geq %bdd% goto N
:Z1
cls
SETLOCAL
set /a "Number1=%~1"
echo year = %Number1%
set /a "Number2=%~2"
echo branch = %Number2%
call:operation Number1,Number2
pause
GOTO :EOF
:operation
cls
echo Choose from the list of Operation given below:
echo [1] UB
echo [3] B
echo [4] C
echo [5] l
echo [6] R
echo [7] JT
echo [8] CT
echo [9] JT
SETLOCAL
set /a "year=%~1"
echo Your have selected year = %year%
set /a "month=%~2"
echo You have selected Branch = %month%
set operation=
set /p operation= Enter your choice:
set /a b=0
set /a bd=9
set /a bdd=10
if %input% equ %b% goto N
if %operation% leq %bd% goto :switch-case-N-%operation% if NOT goto Start2
if %input% geq %bdd% goto N
:switch-case-N-1
echo Januray
echo %year%,%month%,%operation%
goto :switch-case-end
:switch-case-N-2
echo Feburary
echo %year%,%month%,%operation%
goto :switch-case-end
:switch-case-N-3
echo march
echo %year%,%month%,%operation%
goto :switch-case-end
:switch-case-end
echo Task Completed
pause
exit
goto :start2
:Task
cls
echo Choose from the list of Operation given below:
echo [1] UB
echo [3] B
echo [4] C
echo [5] l
echo [6] R
echo [7] JT
echo [8] CT
echo [9] JT
SETLOCAL
set operation=
set /p operation= Enter your choice:
set /a b=0
set /a bd=9
set /a bdd=10
if %input% equ %b% goto N
if %operation% leq %bd% goto :switch-case-N-%operation% if NOT goto Start2
if %input% geq %bdd% goto N
:switch-case-N-1
echo Januray
echo %operation%
goto :switch-case-end
:switch-case-N-2
echo Feburary
echo %year%,%month%,%operation%
goto :switch-case-end
:switch-case-N-3
echo march
echo %year%,%month%,%operation%
goto :switch-case-end
:switch-case-end
echo Task Completed
pause
exit
goto :start2
If if is not working you use:
:switch case %n%=1
statements;
goto :switch case end
etc..
http://lallouslab.net/2016/12/21/batchography-switch-case/
It might be a bit late, but this does it:
set "case1=operation1"
set "case2=operation2"
set "case3=operation3"
setlocal EnableDelayedExpansion
!%switch%!
endlocal
%switch% gets replaced before line execution. Serious downsides:
You override the case variables
It needs DelayedExpansion
Might eventually be usefull in some cases.

Resources