Ctrl + C不能可靠地终止Windows批处理脚本

我正在尝试编写一个批处理脚本,提示用户input一个目录,并将多个文件从这个目录复制到另一个目录。 要做到这一点,我有一个简单的循环,使用标签和set /pinput。 问题是试图摆脱这个循环按ctrl+c并不总是工作。

 :checkloop @set /p READMEPATH=Please enter the location of readme.txt: @if not exist "%READMEPATH%\README.txt" goto somethingmissing @goto allfound :somethingmissing @echo Can't find readme in directory "%READMEPATH%" @goto checkloop :allfound @echo Okay, found 

示例输出是类似的

 Please enter the location of readme.txt: Can't find readme in directory "" Please enter the location of readme.txt: ^CCan't find readme in directory "" Please enter the location of readme.txt: ^CCan't find readme in directory "" Please enter the location of readme.txt: ^CCan't find readme in directory "" Please enter the location of readme.txt: ^CCan't find readme in directory "" Please enter the location of readme.txt: ^CCan't find readme in directory "" Please enter the location of readme.txt: ^CTerminate batch job (Y/N)? y 

按ctrl + c重复的行为,如果我按Enter键和脚本继续,直到它终于起作用。 所需的尝试次数是可变的; 有时会马上工作,有时2-3次,很less需要7次以上。

操作系统是Windows 10。

您可以检查是否定义了READMEPATH。

 :checkloop set "READMEPATH=" set /p READMEPATH=Please enter the location of readme.txt: if not defined READMEPATH exit /b 

但是这不能检测到CTRL-C和ENTER之间的区别。

这是基于版本1.3,由Dave Benham编写,最初发布在阅读按键通过REPLACE – 新功能:getKey,:getAnyKey,:getMaskedInput

更复杂的批次,但作为概念的证明,它区分CTRL + C和ENTER。

 @echo off setlocal for /F %%# in ('forfiles /m "%~nx0" /c "cmd /c echo 0x03"') do set "CTRLC=%%#" & rem capture CTRL-C char for /F %%# in ('copy /Z "%~dpf0" NUL') do set "CR=%%#" & rem capture carriage return char for /F %%# in ('"prompt $H&for %%@ in (1) do rem"') do set "BS=%%#" & rem capture backspace char for /F "tokens=1,2 delims=#" %%# in ('"prompt #$H#$E# & echo on & for %%@ in (1) do rem"') do set "DEL=%%#" & rem capture DEL char :checkloop cls & set "READMEPATH=" <nul set/P "=Please enter the location of readme.txt: " :getPath call :getKey key if "%key%" equ "%CTRLC%" exit/B & rem or whatever you wanna do if "%key%" equ "%CR%" goto:done if "%key%" equ "%BS%" ( <nul set/P=%DEL% set "READMEPATH=%READMEPATH:~0,-1%" ) else ( <nul set/P=%key% set "READMEPATH=%READMEPATH%%key%" ) goto getPath :done if not defined READMEPATH exit/B @if not exist "%READMEPATH%\README.txt" goto somethingmissing @goto allfound :somethingmissing echo(&echo( Can't find readme in directory "%READMEPATH%" pause @goto checkloop :allfound @echo Okay, found endlocal exit/B ::getKey KeyVar [ValidVar] :: :: Read a keypress representing a character between 0x00 and 0xFF and store the :: value in variable KeyVar. Null (0x00), LineFeed (0x0A), and Carriage Return :: (0x0D) will result in an undefined KeyVar. On Windows 10, Ctrl-Z (0x1A) will :: also result in an undefined KeyVar. The simplest way to get an undefined :: KeyVar is to press the [Enter] key. :: :: The optional ValidVar variable defines the values that will be accepted. :: If not given or not defined, then all characters are accepted. If given :: and defined, then only characters within ValidVar are accepted. The first :: character within ValidVar should either be 0, meaning ignore undefined KeyVar, :: or 1, meaning accept undefined KeyVar. The remaining characters represent :: themselves. For example, a ValidVar value of 0YNyn will only accept upper :: or lower case Y or N. A value of 1YNyn will additionally accept [Enter] etc. :: :: Any value (except null) may be entered by holding the [Alt] key and pressing :: the appropriate decimal code on the numeric keypad. For example, holding :: [Alt] and pressing numeric keypad [1] and [0], and then releasing [Alt] will :: result in a LineFeed. :: :: The only way to enter a Null is by holding [Ctrl] and pressing the normal [2] :: :: An alternate way to enter control characters 0x01 through 0x1A is by holding :: the [Ctrl] key and pressing any one of the letter keys [A] through [Z]. :: However, [Ctrl-A], [Ctrl-F], [Ctrl-M], and [Ctrl-V] will be blocked on Win 10 :: if the console has Ctrl key shortcuts enabled. :: :: This function works properly regardless whether delayed expansion is enabled :: or disabled. :: :: :getKey version 1.3 was written by Dave Benham, and originally posted at :: http://www.dostips.com/forum/viewtopic.php?f=3&t=7396 :: :: This work was inspired by posts from carlos and others at :: http://www.dostips.com/forum/viewtopic.php?f=3&t=6382 :: :getkey set "%1=" setlocal disableDelayedExpansion for /f skip^=1^ delims^=^ eol^= %%A in ( 'replace.exe ? . /u /w' ) do for /f delims^=^ eol^= %%B in ("%%A") do ( endlocal if "%%B" equ "" (set "%1=^!") else set "%1=%%B" ) setlocal enableDelayedExpansion if "!%2!" neq "" ( if not defined %1 if "!%2:~0,1!" equ "0" (endlocal&endlocal&goto :getKey) else exit /b set "getKey.key=!%1!" set "mask=!%2:~1!" if not defined mask endlocal&endlocal&goto :getKey if "!getKey.key!" equ "=" ( set "test=a!mask!" for /f "delims=" %%A in ("!test!") do if /i "!test:%%A=%%A!" equ "!test!" endlocal&endlocal&goto :getKey ) for /f delims^=^ eol^= %%A in ("!getKey.key!") do if "!mask:*%%A=!" equ "!mask!" endlocal&endlocal&goto :getKey ) exit /b