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 uncommited changes.
What code would I need for my .bat file to make it say "are you sure", and make me type "y" before it ran the rest of the file? If anything but "y" is typed it should exit execution on that line.
Edit Nov 27
Ok I marked this unanswered again because I still can't figure it out. When I call "exit;" it closes cmd.exe which is not what I want. All this because Windows implemented command buffer wrong [differently than what I am used to at least]
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."
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%== Y goto ...
if %errorlevel%== N exit
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
. 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 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
echo This is an example for prompting a user.
echo/
if exist "%SystemRoot%\System32\choice.exe" goto UseChoice
setlocal EnableExtensions EnableDelayedExpansion
:UseSetPrompt
set "UserChoice=N"
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 errorlevel 2 goto :EOF
:Continue
echo So your are sure. Okay, let's go ...
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?
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 strings comparisons, but result on comparing strings in double quotes on 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 already 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 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/
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.