Batch File Won't Jump to Label - windows

I have an unfinished batch file that wont jump to the :TBS label. It will always go to the :BSO label no matter what you put in for the first question. "A" should go to :BSO and "B" should go to :TBS. I don't know how to fix this. I have tried everything I can think of. Any help appreciated.
#echo off
echo ------------------------------------------Computer Optimization and Fixer 1.1-------------------------------------------
echo.
echo Welcome to Computer Optimization and Fixer 1.1 by Anston
echo.
echo Computer Optimization and Fixer 1.1 will do a basic optimization and fix issues on your computer. For example...
echo It can run sfc, chkdsk, Defrag or Optimize, Disk Cleanup, DISM, troubleshooters, and more.
echo.
set /p A="Would you like to do a basic optimization(A) or fix a certain issue(B)?"
IF %A% EQU A GOTO:BSO
IF %A% EQU B GOTO:TBS
:BSO
echo.
echo Running basic optimization...
pause
start "dfrgui.exe" /wait "C:\Windows\System32\dfrgui.exe"
sfc /scannow
chkdsk /r
start diskclean
GOTO:END
:TBS
echo.
set /p ch="What problem do you have?(Power[A], Internet[B], Performance[C], Files[D], Windows Apps[E], Windows Update[F], Devices[G], Audio[H], Search[I], or Printer[J])
IF %ch% EQU A GOTO:PWR
IF %ch% EQU B GOTO:INT
IF %ch% EQU C GOTO:PRF
IF %ch% EQU D GOTO:FLS
IF %ch% EQU E GOTO:WNA
IF %ch% EQU F GOTO:WNU
IF %ch% EQU G GOTO:DEV
IF %ch% EQU H GOTO:AUD
IF %ch% EQU I GOTO:SCH
IF %ch% EQU J GOTO:PRN
:PWR
echo.
echo Running Troubleshooter...
msdt.exe /id PowerDiagnostic
pause
GOTO:END
:END
cls
echo ------------------------------------------Computer Optimization and Fixer 1.1-------------------------------------------
echo.
echo Thank you for using Computer Optimization and Fixer 1.1
pause

There is a command available since Windows Vista and on Windows Server versions since Windows Server 2003 for choice menus: CHOICE
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ToolVersion=1.1"
cls
echo --------------------- Computer Optimization and Fixer %ToolVersion% ---------------------
echo/
echo Welcome to Computer Optimization and Fixer %ToolVersion% by Anston
echo/
echo Computer Optimization and Fixer %ToolVersion% will do a basic optimization
echo and fix issues on your computer. For example, it can run Check Disk
echo Utility, Disk Space Cleanup Manager for Windows, Disk System Integrity
echo Check and Repair, Disk Defragmenter, troubleshooters, and more.
echo/
echo What do you want to do?
echo/
echo A ... do a basic optimization
echo B ... fix a certain issue
echo E ... do nothing and exit
echo/
%SystemRoot%\System32\choice.exe /C ABE /N /M "Your choice:"
if errorlevel 3 goto :EOF
if errorlevel 2 goto TBS
echo/
echo Running basic optimization...
%SystemRoot%\System32\chkdsk.exe /r
%SystemRoot%\System32\cleanmgr.exe
%SystemRoot%\System32\sfc.exe /scannow
%SystemRoot%\System32\dfrgui.exe
goto END
:TBS
echo/
echo What problem do you have?
echo/
echo A ... Power
echo B ... Internet
echo C ... Performance
echo D ... Files
echo E ... Windows Apps
echo F ... Windows Update
echo G ... Devices
echo H ... Audio
echo I ... Search
echo J ... Printer
echo N ... None of above
echo/
%SystemRoot%\System32\choice.exe /C ABCDEFGHIJN /N /M "Your choice:"
echo/
goto Option%Errorlevel%
:Option1
echo Running diagnostics troubleshooting wizard ...
%SystemRoot%\System32\msdt.exe /id PowerDiagnostic
goto FINISH
:Option2
echo Check for Internet problems ...
goto FINISH
:Option3
echo Check for performance problems ...
goto FINISH
:Option4
echo Check for file problems ...
goto FINISH
:Option5
echo Check for problem with Windows Apps ...
goto FINISH
:Option6
echo Check for Windows update problems ...
goto FINISH
:Option7
echo Check for device problems ...
goto FINISH
:Option8
echo Check for audio problems ...
goto FINISH
:Option9
echo Check for search problems ...
goto FINISH
:Option10
echo Check for printer problems ...
goto FINISH
:Option11
echo Sorry, this tool cannot help you.
:FINISH
echo/
pause
:END
cls
echo --------------------- Computer Optimization and Fixer %ToolVersion% ---------------------
echo/
echo Thank you for using Computer Optimization and Fixer %ToolVersion%
echo/
endlocal
pause
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.
chkdsk /?
choice /?
cleanmgr /?
cls /?
defrag /? ... console version of dfrgui.exe
dism /?
echo /?
endlocal /?
goto /?
if /?
pause /?
set /?
setlocal /?
sfc /?
Please read also:
How does the Windows Command Interpreter (CMD.EXE) parse scripts?
Where does GOTO :EOF return to?
Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?
DosTips forum topic: ECHO. FAILS to give text or blank line - Instead use ECHO/
Note: The execution of disk defragmenter is not necessary on SSD hard disks. So the batch file should check of which type each local drive is before running disk defragmenter on a drive.
PS: The names of the executables used for basic optimizations can be read by clicking with secondary (usually right) mouse button on an executable like sfc.exe, clicking in opened context menu with primary (usually left) mouse button on last menu item Properties, selecting the tab Details and looking on item File description.

Related

Creating a shop. Won't subtract money correctly

I expect to be able to buy items in the shop and have it do the correct subtraction. In the code below, you start out with 10 gold pieces, (gp), but whenever option 2 or 4, to spend 5gp or 1gp, is entered, it takes away all 10gp. I know that it's because it doesn't go past the first if %input%== 1 but I don't know how to fix it, I have tried almost everything, including if/else statements, but I may not have been doing them properly.
:shop
cls
echo You see a middle aged man behind the counter
echo of the shop as well as a younger man sweeping the floors.
echo "Hello young travelers. Welcome, is there anything
echo I can help you find?"
:purchase
echo --------------------------------------------------------
echo %name%
echo Gold: %gp%
echo --------------------------------------------------------
echo.
echo 1) Battleaxe 10gp Stats: 1d8(S) Versatile(1d10)
echo 2) Mace 5gp Stats: 1d6(B)
echo 3) L.Crossbow 20gp Stats: 1d8(P) Range 80/320
echo 4) 5 Bolts 1gp Equip with Crossbow
echo 5) Go Back
echo.
set /p input=Enter:
if %input%== 5 goto main
if %input%== 1
if %gp% LSS 10 goto nofunds
set /a gp= %gp% - 10
goto shopcont
if %input%== 2
if %gp% LSS 5 goto nofunds
set /a gp= %gp% - 5
goto shopcont
if %input%== 3
if %gp% LSS 20 goto nofunds
set /a gp= %gp% - 20
goto shopcont
if %input%== 4
if %gp% LSS 1 goto nofunds
set /a gp= %gp% - 1
goto shopcont
goto shop
:nofunds
cls
echo You don't have enough gold to purchase that item.
pause >nul
goto shop
:shopcont
cls
echo Would you like to purchase anything else?
goto purchase
I am still new at this so examples and explanations would be wonderful!
Please do not tell me to use choice.exe instead of Set /P, unless it will fix the actual issue.
In the below example, I have used Set /P under :purchase to satisfy your ill advised stipulation to not use choice.exe, (which I used under :shopcont instead).
:shop
ClS
Echo You see a middle aged man behind the shop counter, as well as a
Echo younger man sweeping the floor.
Echo(
Echo "Welcome young travellers, is there anything I can help you with?"
:purchase
Set "input="
Set "invalid=true"
Echo(
Echo ------------------------------------------------------------------
Echo(%name%
Echo Gold: %gp%
Echo ------------------------------------------------------------------
Echo(
Echo 1. Battleaxe 10gp [Stats: 1d8(S) Versatile(1d10)]
Echo 2. Mace 5gp [Stats: 1d6(B)]
Echo 3. L.Crossbow 20gp [Stats: 1d8(P) Range 80/320]
Echo 4. 5 Bolts 1gp [Equip with Crossbow]
Echo 5. Go Back
Echo(
Set /P "input=Enter: "
For /L %%A In (1,1,5) Do If "%%~A" == "%input:"=%" Set "invalid="
If Defined invalid ClS & GoTo purchase
If %input% Equ 5 GoTo main
If %input% Equ 4 If %gp% GEq 1 Set /A gp -=1 & GoTo shopcont
If %input% Equ 3 If %gp% GEq 20 Set /A gp -=20 & GoTo shopcont
If %input% Equ 2 If %gp% GEq 5 Set /A gp -=5 & GoTo shopcont
If %input% Equ 1 If %gp% GEq 10 Set /A gp -=10 & GoTo shopcont
Echo You do not have enough gold to purchase that item.
:shopcont
"%__AppDir__%choice.exe" /M "Would you like to purchase anything else"
If "%ErrorLevel%"=="1" ClS & GoTo purchase
Please note that I have tried to replicate that which you posted in your question, this assumes that %gp% and %name% are already defined prior to this code section and that the label :main exists elsewhere in your unposted code.
You asked for examples and explanations, but those are readily available under each command's usage information and via web searches, so I will not be pointlessly including such things.
The usage of command set /P is not recommended for a simple choice menu. A simple typing mistake by user of batch file can easily result in a syntax error on further processing of the batch file detected by Windows command processor resulting in an unexpected exit of batch file execution. A user playing this batch file game by double clicking on it will not be happy on typing for example by mistake " instead of 2 and suddenly the console window is closed because cmd.exe exited batch file processing because of a serious syntax error caused by " and not good coded batch file.
See also:
How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?
Safe number comparison in Windows batch file
However, the main problem is the used syntax on all IF commands. The syntax of command IF can be seen by opening a command prompt, running if /? and reading the output help. if %input%== 1 without a command or a command block starting with ( and ending with matching ) to execute on condition is true on same line results in a syntax error on batch file execution. This can be seen on debugging the batch file.
The indentations have no meaning for cmd.exe regarding to process flow. Windows command processor is not Python. Windows command processor executes one command line respectively command block after the other independent on how many leading spaces or tabs are used to indent the command lines.
See also: How does the Windows Command Interpreter (CMD.EXE) parse scripts?
An arithmetic expression is the string after set /A evaluated by cmd.exe on execution of the batch file. The help output on running set /? explains that within an arithmetic expression it is possible to reference the value of an environment variable by writing just its name without % or ! around variable name. That has two advantages:
If the environment variable does not exist at all, Windows command processor uses value 0 for not existing environment variable. Using %NotExistingVariable% in an arithmetic expression results in a syntax error because of this string is replaced by nothing which usually results in a missing operand error on evaluation of the arithmetic expression.
Environment variables can be modified with arithmetic expressions multiple times in a command block without usage of delayed expansion.
For that reason set /a gp= %gp% - 10 is not a recommended syntax to decrement the environment variable gp by 10. Better is using set /A gp=gp - 10 and best set /A gp-=10.
The DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/ explains that echo. can fail to print an empty line into console window and that echo/ or echo( is better for this task.
A minimal, complete, and verifiable example for this task is following batch file:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "gp=50"
set "name=B1u3Soul"
:Shop
cls
echo You see a middle aged man behind the counter
echo of the shop as well as a younger man sweeping the floors.
echo "Hello young travelers. Welcome, is there anything
echo I can help you find?"
:Purchase
echo --------------------------------------------------------
echo %name%
echo Gold: %gp%
echo --------------------------------------------------------
echo/
echo 1) Battleaxe 10gp Stats: 1d8(S) Versatile(1d10)
echo 2) Mace 5gp Stats: 1d6(B)
echo 3) L.Crossbow 20gp Stats: 1d8(P) Range 80/320
echo 4) 5 Bolts 1gp Equip with Crossbow
echo 5) Go Back
echo/
%SystemRoot%\System32\choice.exe /C 12345 /N /M "Enter: "
if errorlevel 5 goto Main
if errorlevel 4 set "GoldAmount=1" & goto GoldInPurse
if errorlevel 3 set "GoldAmount=20" & goto GoldInPurse
if errorlevel 2 set "GoldAmount=5" & goto GoldInPurse
set "GoldAmount=10"
:GoldInPurse
if %gp% LSS %GoldAmount% goto NoFunds
set /A gp-=GoldAmount
echo/
%SystemRoot%\System32\choice.exe /C YN /N /M "Would you like to purchase anything else [Y/N]? "
cls
if errorlevel 2 goto Main
goto Purchase
:NoFunds
echo/
echo You don't have enough gold to purchase that item.
pause >nul
goto Shop
:Main
endlocal
See also single line with multiple commands using Windows batch file for an explanation of operator & as used in this batch file.
It would be of course possible to use just choice instead of %SystemRoot%\System32\choice.exe. But the usage of full qualified file name (drive + path + file name + file extension) makes the batch file independent on environment defined outside the batch file. For this batch file it does not matter how PATH and PATHEXT is defined on starting the batch file. It depends only on environment variable SystemRoot defined by Windows and which is not modified by applications or users in general.
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.
choice /?
cls /?
echo /?
endlocal /?
goto /?
if /?
pause /?
set /?
setlocal /?
See also:
What are the ERRORLEVEL values set by internal cmd.exe commands?
Which cmd.exe internal commands clear the ERRORLEVEL to 0 upon success?
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
Microsoft article about Using command redirection operators

I am using a Batch File to search a list of functions for an exact match, wondering if its possible to do a keyword search instead

I am using a Batch File to search a list of functions for an exact match, wondering if its possible to do a key word search, so right now i have to type "open cmd"
(variations on spacing and capital letters are accounted for)
Id like to switch it over to a system that can look for "cmd" and perform the action so "hey, open cmd please" would yield the same result as the old system
Old system:
setlocal
:: /STARTUP
set speech=start scripts\nircmd.exe speak text
cls
:begin
set TALK=TypeSomething
SET /P TALK=
set TALK=%TALK:?=%
call :%TALK: =% 2>NUL
if %errorlevel% equ 0 goto begin
exit /B 0
:unknown
echo Old function no longer supported
:opencmd
:BOSopencmd
:cmd
echo Command Prompt has now been opened in a new window, sir.
%speech% "Command Prompt has now been opened in a new window, sir."
start scripts\cmd.bat
exit /B 0
It is based of a chat bot i tried to make in middle school so the %speech% is not an important item, i can add that and the echo later. I just need a system that works like the old one if possible. The other i can have any number of functions with
:cmd
start cmd
Exit /B 0
or
:reddit
start http://www.reddit.com/
exit /B 0
at these need to be able to stack. I can transition to having scripts for each function in a separate batch files if needed. Ive tried trying findstr but it wasn't giving the desired results. Ive exhausted my knowledge on what i might be able to do but I've come up short lol, If you are having trouble understanding what i'm asking don't hesitate to let me know
I learn by taking things apart so partial code is appreciated but will not be much help until after I've figured out what does what .
Here's a sample of how you might approach it using ECHO, FINDSTR, and CALL (This is a modified example from the original per your request to be able to process multiple keywords):
#echo off
set TST_FNDFLG=FALSE
set TST_USRANS=
set /P TST_USRANS=Enter keywords:
if "%TST_USRANS%" == "" goto ENDIT
echo %TST_USRANS% | findstr /i "CMD" >NUL 2>&1
if ERRORLEVEL 1 goto TRYRED
call :DOCMD
:TRYRED
echo %TST_USRANS% | findstr /i "REDDIT" >NUL 2>&1
if ERRORLEVEL 1 goto TRYGOO
call :DORED
:TRYGOO
echo %TST_USRANS% | findstr /i "GOOGLE" >NUL 2>&1
if ERRORLEVEL 1 goto TRYEND
call :DOGOO
goto TRYEND
:DOCMD
if [%TST_FNDFLG%] == [FALSE] echo.
echo CMD was found in "%TST_USRANS%"
set TST_FNDFLG=TRUE
goto :EOF
:DORED
if [%TST_FNDFLG%] == [FALSE] echo.
echo REDDIT was found in "%TST_USRANS%"
set TST_FNDFLG=TRUE
goto :EOF
:DOGOO
if [%TST_FNDFLG%] == [FALSE] echo.
echo GOOGLE was found in "%TST_USRANS%"
set TST_FNDFLG=TRUE
goto :EOF
:TRYEND
echo.
if [%TST_FNDFLG%] == [TRUE] echo No more keywords found
if [%TST_FNDFLG%] == [FALSE] echo Did not find any known keywords
goto ENDIT
:ENDIT
echo.
set TST_USRANS=
set TST_FNDFLG=

Running Portable Exe file through batch file

I have created a batch file which runs multiple commands in the Windows command prompt, which is working just fine, however, I want to run a portable exe file through the same batch file as well. E.g. if I transfer the zip file to another computer, all I would like to do is run the batch file and that portable exe would run along with the other commands as well
:start
cls
color 1A
cls
#echo off
echo.
echo.
echo.
echo ********************************************
echo ************* Test Program **************
echo ********************************************
echo.
echo.
echo.
echo 01) System information
echo 02) Ping
echo 03) IP configuration
echo 04) Verify Drivers
echo 05) Driver List
echo 06) Get Serial Number
echo 07) Disk Defragmentation
echo 08) DiskPart
echo 09) Repair Load Preferences
echo 10) Run CCleaner
echo.
REM This is a test program
REM echo This is a Test Program
set /pnum= Type the corresponding number to perform an operation:
if %num%==01 (
cls
systeminfo
)
if %num%==02 (
cls
ping www.google.com
)
if %num%==03 (
cls
ipconfig /all
)
if %num%==04 (
cls
verifier
)
if %num%==05 (
cls
driverquery
)
if %num%==06 (
cls
wmic bios get serialnumber
)
if %num%==07 (
defrag c: /a
pause
cls
)
if %num%==08 (
diskpart
pause
cls
)
if %num%==09 (
cls
lodctr /r /f
echo.
pause
)
if %num%==10 (
cls
C:\Users\kumar\Desktop\CCleaner.exe
echo.
pause)
set /p choice="Do you want to restart? Press 'Y' to continue, or any other key to exit: "
if '%choice%'=='y' goto start
So for example in the last condition I am running CCleaner which is on the Desktop at the moment, but if i copy a zip file which consists of the BAT File and the CCleaner.exe how would i enable it to run on another PC after copying?
Any help would be appreciated.
If the "portable" directory will contain all executable files, another way is to make the location of the .bat script the current working directory.
#ECHO OFF
PUSHD "%~dp0"
: do things, the directory of the .bat script is the current directory
POPD
EXIT /B 0
place your tools into the same folder as the batchfile and instead of
C:\Users\kumar\Desktop\CCleaner.exe
do
%~dp0\CCleaner.exe
%~dp0 is Drive and Path of your batchfile.
You may also put your tools into a subdir (tools) and:
%~dp0\tools\CCleaner.exe
This could be useful in the case your app uses some system variables (e.g. PATH)
and you might want to reassign them locally before starting the application. The provided .exe will pass control to a .bat where you can do this and much more.
At the end of this .bat run the App.exe

Batch script prompt needs multiple entries

So I have this subroutine that I want to call from another location in a batch file. The functions work as desired, but for some reason I cant pin down, the prompt wants to have the user enter something TWICE, before it will accept anything.
Say, if I enter "0", to go back to a previous menu, it takes me right back to the prompt, and I have to enter "0" again before it will actually go back to the previous menu (elsewhere in my main script).
I can, say, enter "w" (or any other value), then the second time, enter the one I actually WANT to use, and it will finally do it.
This is driving me nuts.
:subfullbackup
cls
if exist "%current%\Backup\Full_Backup" (
Echo Backup folder already exists
Echo.
Echo [o] Overwrite local device files with existing local files
Echo [w] Wipe current local backup and start fresh
Echo.
set /p choice=Select:
if %choice% == o (
Echo.
Echo Depending on how much data you have,
Echo this could take a couple hours.
Echo.
Echo Backing up...
adb pull /sdcard/ "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo -= BACKUP COMPLETE =-
Pause
Goto :backup
)
if %choice% == w (
Echo.
Echo Removing all current local backup files in 'Full_Backup'
rmdir /S /Q "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo Depending on how much data you have,
Echo this could take a couple hours.
Echo.
Echo Backing up...
adb pull /sdcard/ "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo -= BACKUP COMPLETE =-
Pause
Goto :backup
)
if not %choice% == o goto subfullbackup
if not %choice% == w goto subfullbackup
) else (
Echo.
Echo Depending on how much data you have,
Echo this could take a couple hours.
Echo.
Echo Backing up...
adb pull /sdcard/ "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo -= BACKUP COMPLETE =-
Pause
Goto :backup
)
Goto :eof
Your batch code with using delayed expansion, enabled at top of the batch script with command setlocal which additionally creates a copy of all environment variables and remembering also current directory for restoring the variables list, current directory and current states of command extensions and delayed expansion on endlocal or leaving batch processing:
#echo off
setlocal EnableDelayedExpansion
set "current=%CD%"
:FullBackup
cls
if exist "%current%\Backup\Full_Backup" (
Echo Backup folder already exists
Echo.
Echo [o] Overwrite local device files with existing local files
Echo [w] Wipe current local backup and start fresh
Echo.
set "UserChoice="
set /p "UserChoice=Select: "
if /I "!UserChoice!" == "o" (
Echo.
Echo Depending on how much data you have,
Echo this could take a couple hours.
Echo.
Echo Backing up...
adb.exe pull /sdcard/ "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo -= BACKUP COMPLETE =-
Pause
Goto DoBackup
)
if /I "!UserChoice!" == "w" (
Echo.
Echo Removing all current local backup files in 'Full_Backup'
rmdir /S /Q "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo Depending on how much data you have,
Echo this could take a couple hours.
Echo.
Echo Backing up...
adb.exe pull /sdcard/ "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo -= BACKUP COMPLETE =-
Pause
Goto DoBackup
)
goto FullBackup
) else (
Echo.
Echo Depending on how much data you have,
Echo this could take a couple hours.
Echo.
Echo Backing up...
adb.exe pull /sdcard/ "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo -= BACKUP COMPLETE =-
Pause
Goto DoBackup
)
Goto :EOF
:DoBackup
But your batch code could be also written without delayed expansion and much more compact avoiding duplicate code lines:
#echo off
set "current=%CD%"
:FullBackup
cls
if exist "%current%\Backup\Full_Backup" goto PromptBackup
:OverwriteBackup
Echo.
Echo Depending on how much data you have,
Echo this could take a couple hours.
Echo.
Echo Backing up...
adb.exe pull /sdcard/ "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo -= BACKUP COMPLETE =-
Pause
Goto DoBackup
:PromptBackup
Echo Backup folder already exists
Echo.
Echo [o] Overwrite local device files with existing local files
Echo [w] Wipe current local backup and start fresh
Echo.
set "UserChoice="
set /p "UserChoice=Select: "
if /I "%UserChoice%" == "o" goto OverwriteBackup
if /I not "%UserChoice%" == "w" goto FullBackup
Echo.
Echo Removing all current local backup files in 'Full_Backup'
rmdir /S /Q "%current%\Backup\Full_Backup" >nul 2>&1
goto OverwriteBackup
:DoBackup
Some notes about small changes in code:
choice (SS64 article) is a standard Windows command. Therefore it is advisable to avoid choice (Microsoft article) as name for an environment variable or label. UserChoice (CamelCase spelling for easier reading) is used instead of choice.
backup (SS64 article) is not a standard Windows command, but a standard SQL command. Therefore it is also advisable to avoid backup as name for an environment variable or label. DoBackup is used instead in batch code above.
It is advisable to define a default for an environment variable before prompting a user. The user can hit just RETURN or ENTER in which case the environment variable keeps its value.
The environment variable is cleared with set "UserPoint=" before prompting the user and therefore the variable does not exist when user enters nothing.
Possible would be also set "UserPoint=o" or set "UserPoint=w" to define a valid default value.
Comparing strings with user input should be done always with using double quotes to avoid an exit of batch processing caused by a syntax error when user inputs nothing.
if %choice% == w ( becomes if == w ( when the user enters nothing which is a syntax error and results in breaking batch processing by command processor.
if /I "%UserChoice%" == "w" ( becomes if /I "" == "w" when the user enters nothing in code above which is still valid batch code and can be therefore processed.
Note: User could now break batch processing by entering "w".
But it can be expected here that the user does not input 1 or more double quotes on being asked for o or w.
On comparing strings entered by user with predefined strings it is advisable to do case-insensitive string comparisons if letters are included in the compared strings.
The option /I changes a string comparison from case-sensitive to case-insensitive.
So now the user can enter also O or W and this is interpreted like o or w.

How can I make an "are you sure" prompt in a Windows batch file?

I have a batch file that automates copying a bunch of files from one place to the other and back for me. Only thing is as much as it helps me I keep accidentally selecting that command off my command buffer and mass overwriting uncommitted changes.
What code would I need for my .bat file to make it output "Are you sure?", and make me type Y before it ran the rest of the file?
If anything other than Y is typed, it should exit execution on that line.
When I call exit, it closes cmd.exe which is not what I want.
You want something like:
#echo off
setlocal
:PROMPT
SET /P AREYOUSURE=Are you sure (Y/[N])?
IF /I "%AREYOUSURE%" NEQ "Y" GOTO END
echo ... rest of file ...
:END
endlocal
try the CHOICE command, e.g.
CHOICE /C YNC /M "Press Y for Yes, N for No or C for Cancel."
There are two commands available for user prompts on Windows command line:
set with option /P available on all Windows NT versions with enabled command extensions and
choice.exe available by default on Windows Vista and later Windows versions for PC users and on Windows Server 2003 and later server versions of Windows.
set is an internal command of Windows command processor cmd.exe. The option /P to prompt a user for a string is available only with enabled command extensions which are enabled by default as otherwise nearly no batch file would work anymore nowadays.
choice.exe is a separate console application (external command) located in %SystemRoot%\System32. File choice.exe of Windows Server 2003 can be copied into directory %SystemRoot%\System32 on a Windows XP machine for usage on Windows XP like many other commands not available by default on Windows XP, but available by default on Windows Server 2003.
It is best practice to favor usage of CHOICE over usage of SET /P because of the following reasons:
CHOICE accepts only keys (respectively characters read from STDIN) specified after option /C (and Ctrl+C and Ctrl+Break) and outputs an error beep if the user presses a wrong key.
CHOICE does not require pressing any other key than one of the acceptable ones. CHOICE exits immediately once an acceptable key is pressed while SET /P requires that the user finishes input with RETURN or ENTER.
It is possible with CHOICE to define a default option and a timeout to automatically continue with default option after some seconds without waiting for the user.
The output is better on answering the prompt automatically from another batch file which calls the batch file with the prompt using something like echo Y | call PromptExample.bat on using CHOICE.
The evaluation of the user's choice is much easier with CHOICE because of CHOICE exits with a value according to pressed key (character) which is assigned to ERRORLEVEL which can be easily evaluated next.
The environment variable used on SET /P is not defined if the user hits just key RETURN or ENTER and it was not defined before prompting the user. The used environment variable on SET /P command line keeps its current value if defined before and user presses just RETURN or ENTER.
The user has the freedom to enter anything on being prompted with SET /P including a string which results later in an exit of batch file execution by cmd because of a syntax error, or in execution of commands not included at all in the batch file on not good coded batch file. It needs some efforts to get SET /P secure against by mistake or intentionally wrong user input.
Here is a prompt example using preferred CHOICE and alternatively SET /P on choice.exe not available on used computer running Windows.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
echo This is an example for prompting a user.
echo/
if exist "%SystemRoot%\System32\choice.exe" goto UseChoice
setlocal EnableExtensions EnableDelayedExpansion
:UseSetPrompt
set "UserChoice="
set /P "UserChoice=Are you sure [Y/N]? "
set "UserChoice=!UserChoice: =!"
if /I "!UserChoice!" == "N" endlocal & goto :EOF
if /I not "!UserChoice!" == "Y" goto UseSetPrompt
endlocal
goto Continue
:UseChoice
%SystemRoot%\System32\choice.exe /C YN /N /M "Are you sure [Y/N]?"
if not errorlevel 1 goto UseChoice
if errorlevel 2 goto :EOF
:Continue
echo So you are sure. Okay, let's go ...
rem More commands can be added here.
endlocal
Note: This batch file uses command extensions which are not available on Windows 95/98/ME using command.com instead of cmd.exe as command interpreter.
The command line set "UserChoice=!UserChoice: =!" is added to make it possible to call this batch file with echo Y | call PromptExample.bat on Windows NT4/2000/XP and do not require the usage of echo Y| call PromptExample.bat. It deletes all spaces from string read from STDIN before running the two string comparisons.
echo Y | call PromptExample.bat results in YSPACE getting assigned to environment variable UserChoice. That would result on processing the prompt twice because of "Y " is neither case-insensitive equal "N" nor "Y" without deleting first all spaces. So UserChoice with YSPACE as value would result in running the prompt a second time with option N as defined as default in the batch file on second prompt execution which next results in an unexpected exit of batch file processing. Yes, secure usage of SET /P is really tricky, isn't it?
choice.exe exits with 0 in case of the user presses Ctrl+C or Ctrl+Break and answers next the question output by cmd.exe to terminate the batch job with N for NO. For that reason the condition if not errorlevel 1 goto UserChoice is added to prompt the user once again for a definite answer on the prompt by batch file code with Y or N. Thanks to dialer for the information about this possible special use case.
The first line below the batch label :UseSetPrompt could be written also as:
set "UserChoice=N"
In this case the user choice input is predefined with N which means the user can hit just RETURN or ENTER (or Ctrl+C or Ctrl+Break and next N) to use the default choice.
The prompt text is output by command SET as written in the batch file. So the prompt text should end usually with a space character. The command CHOICE removes from prompt text all trailing normal spaces and horizontal tabs and then adds itself a space to the prompt text. Therefore the prompt text of command CHOICE can be written without or with a space at end. That does not make a difference on displayed prompt text on execution.
The order of user prompt evaluation could be also changed completely as suggested by dialer.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
echo This is an example for prompting a user.
echo/
if exist "%SystemRoot%\System32\choice.exe" goto UseChoice
setlocal EnableExtensions EnableDelayedExpansion
:UseSetPrompt
set "UserChoice="
set /P "UserChoice=Are you sure [Y/N]? "
set "UserChoice=!UserChoice: =!"
if /I not "!UserChoice!" == "Y" endlocal & goto :EOF
endlocal
goto Continue
:UseChoice
%SystemRoot%\System32\choice.exe /C YN /N /M "Are you sure [Y/N]?"
if not errorlevel 2 if errorlevel 1 goto Continue
goto :EOF
:Continue
echo So you are sure. Okay, let's go ...
endlocal
This code results in continuation of batch file processing below the batch label :Continue if the user pressed definitely key Y. In all other cases the code for N is executed resulting in an exit of batch file processing with this code independent on user pressed really that key, or entered something different intentionally or by mistake, or pressed Ctrl+C or Ctrl+Break and decided next on prompt output by cmd not terminating the batch job.
For even more details on usage of SET /P and CHOICE for prompting user for a choice from a list of options see answer on How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?
Some more hints:
IF compares the two strings left and right of the comparison operator with including the double quotes. So case-insensitive compared is not the value of UserChoice with N and Y, but the value of UserChoice surrounded by " with "N" and "Y".
The IF comparison operators EQU and NEQ are designed primary for comparing two integers in range -2147483648 to 2147483647 and not for comparing two strings. EQU and NEQ work also for string comparisons, but result on comparing strings in double quotes after a useless attempt to convert left string to an integer. EQU and NEQ can be used only with enabled command extensions. The comparison operators for string comparisons are == and not ... == which work even with disabled command extensions as even command.com of MS-DOS and Windows 95/98/ME supported them. For more details on IF comparison operators see Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files.
The command goto :EOF requires enabled command extensions to really exit batch file processing. For more details see Where does GOTO :EOF return to?
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.
choice /?
echo /?
endlocal /?
goto /?
if /?
set /?
setlocal /?
See also:
This answer for details about the commands SETLOCAL and ENDLOCAL.
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
It explains the reason for using syntax set "variable=value" on assigning a string to an environment variable.
Single line with multiple commands using Windows batch file for details on if errorlevel X behavior and operator &.
Microsoft documentation for using command redirection operators explaining the redirection operator | and handle STDIN.
Wikipedia article about Windows Environment Variables for an explanation of SystemRoot.
DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/
The choice command is not available everywhere. With newer Windows versions, the set command has the /p option you can get user input
SET /P variable=[promptString]
see set /? for more info
Here a bit easier:
#echo off
set /p var=Are You Sure?[Y/N]:
if %var%== Y goto ...
if not %var%== Y exit
or
#echo off
echo Are You Sure?[Y/N]
choice /c YN
if %errorlevel%==1 goto yes
if %errorlevel%==2 goto no
:yes
echo yes
goto :EOF
:no
echo no
Here's my go-to method for a yes/no answer.
It's case-insensitive also.
This just checks for the errors given by the input and sets the choice variable to whatever you require so it can be used below in the code.
#echo off
choice /M "[Opt 1] Do you want to continue [Yes/No]"
if errorlevel 255 (
echo Error
) else if errorlevel 2 (
set "YourChoice=will not"
) else if errorlevel 1 (
set "YourChoice=will"
) else if errorlevel 0 (
goto :EOF
)
echo %YourChoice%
pause
You can also use 'Choice' command
#echo off
echo Sure?
CHOICE /C YN
IF %ERRORLEVEL% EQU 1 goto CONTINUE
IF %ERRORLEVEL% EQU 2 goto END
:END
exit
:CONTINUE
echo hi
pause
If you want to the batch program to exit back to the prompt and not close the prompt (A.K.A cmd.exe) you can use "exit /b".
This may help.
set /p _sure="Are you sure?"
::The underscore is used to ensure that "sure" is not an enviroment
::varible
if /I NOT "_sure"=="y" (
::the /I makes it so you can
exit /b
) else (
::Any other modifications...
)
Or if you don't want to use as many lines...
Set /p _sure="Are you sure?"
if /I NOT "_sure"=="y" exit /b
::Any other modifications and commands.
Hope this helps...
Here is a simple example which I use in a backup (.bat / batch) script on Windows 10, which allows me to have different options when making backups.
...
:choice
set /P c=Do you want to rsync the archives to someHost[Y/N]?
if /I "%c%" EQU "Y" goto :syncthefiles
if /I "%c%" EQU "N" goto :doonotsyncthefiles
goto :choice
:syncthefiles
echo rsync files to somewhere ...
bash -c "rsync -vaz /mnt/d/Archive/Backup/ user#host:/home/user/Backup/blabla/"
echo done
:doonotsyncthefiles
echo Backup Complete!
...
You can have as many as you need of these blocks.
You can consider using a UI confirmation.
With yesnopopup.bat
#echo off
for /f "tokens=* delims=" %%# in ('yesnopopup.bat') do (
set "result=%%#"
)
if /i result==no (
echo user rejected the script
exit /b 1
)
echo continue
rem --- other commands --
the user will see the following and depending on the choice the script will continue:
with absolutely the same script you can use also iexpYNbutton.bat which will produce similar popup.
With buttons.bat you can try the following script:
#echo off
for /f "tokens=* delims=" %%# in ('buttons.bat "Yep!" "Nope!" ') do (
set "result=%%#"
)
if /i result==2 (
echo user rejected the script
exit /b 1
)
echo continue
rem --- other commands --
and the user will see:
I would do it in the following way to make sure the testing and variables are correct during looping etc..
:: rem at the top of the script
setlocal enabledelayedexpansion
:: choice example
CHOICE /C YNC /M "Continue? Press Y for Yes, N for No or C for Cancel."
If /I "[!errorlevel!]" NEQ "[1]" ( GOTO START_OVER )
There are so many answers, but none of them seems to be simple and straight forward. This is the code I am using:
choice /M "Do you want to continue?"
if %errorlevel% EQU 1 (
... run your code lines here
)
First, open the terminal.
Then, type
cd ~
touch .sure
chmod 700 .sure
Next, open .sure and paste this inside.
#!/bin/bash --init-file
PS1='> '
alias y='
$1
exit
'
alias n='Taskkill /IM %Terminal% /f'
echo ''
echo 'Are you sure? Answer y or n.'
echo ''
After that, close the file.
~/.sure ; ENTER COMMAND HERE
This will give you a prompt of are you sure before continuing the command.
Open terminal. Type the following
echo>sure.sh
chmod 700 sure.sh
Paste this inside sure.sh
#!\bin\bash
echo -n 'Are you sure? [Y/n] '
read yn
if [ "$yn" = "n" ]; then
exit 1
fi
exit 0
Close sure.sh and type this in terminal.
alias sure='~/sure&&'
Now, if you type sure before typing the command it will give you an are you sure prompt before continuing the command.
Hope this is helpful!

Resources