我有一个批处理文件,可以自动将大量文件从一个地方复制到另一个地方,然后再复制回来。但问题是,尽管它帮了我很多忙,但我经常不小心从我的命令缓冲区中选择该命令,并且会导致还未提交的更改被覆盖。
我需要在我的.bat文件中添加什么代码,才能使其输出“你确定吗?”,并要求我在运行文件的其余部分之前输入 Y ?
如果键入除 Y 以外的任何内容,则应退出该行的执行。
当我调用exit
时,它会关闭cmd.exe
,这不是我想要的。
我有一个批处理文件,可以自动将大量文件从一个地方复制到另一个地方,然后再复制回来。但问题是,尽管它帮了我很多忙,但我经常不小心从我的命令缓冲区中选择该命令,并且会导致还未提交的更改被覆盖。
我需要在我的.bat文件中添加什么代码,才能使其输出“你确定吗?”,并要求我在运行文件的其余部分之前输入 Y ?
如果键入除 Y 以外的任何内容,则应退出该行的执行。
当我调用exit
时,它会关闭cmd.exe
,这不是我想要的。
@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
尝试使用CHOICE命令,例如:
CHOICE /C YNC /M "Press Y for Yes, N for No or C for Cancel."
在Windows命令行中,有两个可用于用户提示的命令:
set是Windows命令处理器cmd.exe
的内部命令。提示用户输入字符串的/P
选项仅在启用命令扩展时可用,默认情况下启用命令扩展,否则几乎没有批处理文件能够正常工作。
choice.exe是一个独立的控制台应用程序(外部命令),位于%SystemRoot%\System32
中。Windows Server 2003的choice.exe
文件可以复制到Windows XP机器上的%SystemRoot%\System32
目录中,以便在Windows XP上使用,就像许多其他默认不可用于Windows XP但在Windows Server 2003上默认可用的命令一样。
出于以下原因,最好使用CHOICE而不是SET /P:
/C
后指定的键(从 STDIN 读取的字符),如果用户按下错误的键,则输出错误提示音。echo Y | call PromptExample.bat
的方式从另一个批处理文件自动回答提示时,CHOICE 的输出效果更好。choice.exe
的提示示例。@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 & exit /B
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 exit /B
:Continue
echo So you are sure. Okay, let's go ...
rem More commands can be added here.
endlocal
注意:此批处理文件使用命令扩展,不支持在Windows 95/98/ME上使用command.com
作为命令解释器,而应该使用cmd.exe
。
添加命令行set "UserChoice=!UserChoice: =!"
是为了使其能够在Windows NT4/2000/XP上通过echo Y | call PromptExample.bat
调用,而不需要使用echo Y| call PromptExample.bat
。它会在运行两个字符串比较之前从STDIN读取的字符串中删除所有空格。
echo Y | call PromptExample.bat
的结果是将YSPACE分配给环境变量UserChoice
。这会导致处理提示两次,因为"Y "
既不是大小写不敏感等于"N"
,也不是等于"Y"
,需要先删除所有空格。因此,UserChoice
的值为YSPACE,将导致在第二个提示执行中再次运行提示,并使用批处理文件中定义的默认选项N
,从而导致意外退出批处理文件处理。是的,安全使用SET /P确实很棘手,不是吗?
choice.exe
在用户按下 Ctrl+C 或 Ctrl+Break 并在接下来回答由 cmd.exe
输出的问题以使用 N 终止批处理作业的情况下,将以退出代码 0
退出。因此,条件 if not errorlevel 1 goto UserChoice
被添加以再次提示用户使用 Y 或 N 的批处理文件代码中的提示来确定答案。感谢 dialer 提供关于这种可能的特殊用例的信息。
批处理标签 :UseSetPrompt
下方的第一行也可以写成:
set "UserChoice=N"
在这种情况下,用户选择输入是预定义的N
,这意味着用户可以只按RETURN或ENTER(或Ctrl+C或Ctrl+Break和下一个N)来使用默认选择。
提示文本由批处理文件中的命令SET输出。因此,提示文本通常应以空格字符结尾。命令CHOICE从提示文本中删除所有尾随的普通空格和水平制表符,然后将自己的空格添加到提示文本中。因此,命令CHOICE的提示文本可以写成带有或不带有末尾空格。这在执行时对显示的提示文本没有影响。
用户提示评估的顺序也可以完全更改,如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 & exit /B
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
exit /B
:Continue
echo So you are sure. Okay, let's go ...
endlocal
如果用户按下了确定键Y,则此代码将导致在批处理标签:Continue
下继续进行批处理文件处理。否则,执行N的代码,结果退出批处理文件处理并独立于用户是否真正按下该键、故意或错误地输入其他内容,或按下Ctrl+C或Ctrl+Break并决定接下来的提示输出由cmd
不终止批处理作业。
有关使用SET /P和CHOICE提示用户从选项列表中选择的详细信息,请参阅 如何在 Windows 命令解释程序上停止在不正确的用户输入时退出批处理文件执行?上的答案。
更多提示:
UserChoice
的值与 N
和 Y
进行大小写不敏感的比较,而是将 UserChoice
的值用双引号括起来,再与 "N"
和 "Y"
进行比较。EQU
和 NEQ
主要用于比较范围在 -2147483648 到 2147483647 之间的两个整数,而不是用于比较两个字符串。虽然 EQU
和 NEQ
也可以用于字符串比较,但在尝试将左侧字符串转换为整数后,结果是对双引号中的字符串进行比较。只有启用命令扩展时,才能使用 EQU
和 NEQ
运算符。用于字符串比较的运算符是 ==
和 not ... ==
,即使禁用了命令扩展,它们也能正常工作,因为 MS-DOS 和 Windows 95/98/ME 的 command.com
也支持这些运算符。有关 IF 比较运算符的更多详细信息,请参阅Windows 批处理文件中等效于 NEQ、LSS、GTR 等的符号。goto :EOF
需要启用命令扩展才能真正退出批处理文件的处理过程。有关详细信息,请参阅GOTO :EOF 返回到哪里? 也可以使用 exit /B
,即使禁用了命令扩展,它也能正常工作,但会输出一个禁用命令扩展的错误消息。在任何执行环境中,都可以使用 exit /B 2>nul
来退出批处理文件的处理过程,而不显示任何错误消息。在这两个批处理文件示例中,使用 exit /B
是因为它比 goto :EOF
更短。由于执行环境在批处理文件的前两行命令中已经完全定义,所以这两个命令在示例中都能正常工作。为了理解所使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。
choice /?
echo /?
endlocal /?
exit /?
goto /?
if /?
set /?
setlocal /?
另请参见:
set "variable=value"
来将字符串分配给环境变量的原因。if errorlevel X
行为和运算符&
的详细信息,请参见使用Windows批处理文件的多个命令的单行。|
和句柄STDIN的用法。SystemRoot
的解释,请参见维基百科文章Windows环境变量。CHOICE.COM
。但是,在 Windows NT4、Windows 2000 和 Windows XP 中,默认情况下没有安装 choice.exe
。CHOICE.COM
也可以在 NT4、Windows 2000 和 Windows XP 上使用,但最好使用适当的资源工具包中的 32 位 choice.exe
。请参阅 Rob van der Woude 的页面关于 CHOICE。CHOICE.COM
和 choice.exe
之间的选项部分不同。然而,问题不是关于 DOS。 - Mofiif Cancel do CancelAction else do YesAction
,而是使用if Yes do YesAction else do CancelAction
或者if not Yes do CancelAction else do YesAction
。重点是不要在if语句中检查Cancel条件,而是使用Yes条件。这也适用于CHOICE。CHOICE 可以返回0或255(既不是1也不是2),此时程序的行为不正确。 - dialerchoice
命令并非在所有地方都可用。对于较新的Windows版本,set
命令具有/p
选项,您可以使用该选项获取用户输入。
SET /P variable=[promptString]
查看 set /?
以获取更多信息。
这里稍微简单一些:
@echo off
set /p var=Are You Sure?[Y/N]:
if %var%== Y goto ...
if not %var%== Y exit
或者@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
它不区分大小写。
这只是检查输入中给出的错误,并将choice
变量设置为您需要的任何值,以便在下面的代码中使用。
@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
您还可以使用“Choice”命令
@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
有很多答案,但似乎没有一个简单明了的。这是我正在使用的代码:
choice /M "Do you want to continue?"
if %errorlevel% EQU 1 (
... run your code lines here
)
我会以以下方式进行,以确保在循环等过程中测试和变量是正确的。
:: 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 )
...
: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!
...
您可以拥有任意数量的这些块。
SET AREYOUSURE=N
,以便在该命令窗口中之前已运行过脚本的情况下清除选择。如果没有它,那么默认值将保留先前选择的选项。 - isapirsetlocal
和endlocal
可以解决这个问题。%AREYOUSURE%
在endlocal
之后将不再存在。 - user837703SET /P AREYOUSURE=Are you sure (Y/[N])?
替换为SET /P AREYOUSURE=Are you sure Y/[N]?
,去掉括号以避免影响代码。 - DefToneR