2016-09-13 6 views
3

ユーザーにディレクトリを要求し、このディレクトリから別のディレクトリに複数のファイルをコピーするバッチスクリプトを作成しようとしています。これを行うには、ラベルとset /pを入力するための簡単なループがあります。問題は、ctrl+cを押してこのループから抜け出そうとしても、必ずしも機能しないということです。Ctrl + CがWindowsバッチスクリプトを確実に終了しない

: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になることもありますが、めったに7回以上かかることはまれです。

OSはWindows 10です。

+2

私は、SET呼び出し後に%errorlevel%をチェックして失敗したことを確認する必要があると思います。 –

+2

@HansPassant '%errorlevel%'の問題は、CTRL-Cと空の入力に対して1に設定されていることです。 – jeb

+0

おめでとう、両方の理由で試してみることをやめてください。 –

答えて

2

READMEPATHが定義されているかどうかを確認できます。

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

ただし、空の行に対してCTRL-CとEnterキーを押したときの違いを検出することはできません。

+0

これは適切な回避策として機能しますが、私は本当にctrl + cがここで動作しない理由に真剣に関心があります。私はctrl + cとENTERが同じであるとは思わないが、私の状況には問題がある。 – DylanStreb

1

これは、のgetKeyバージョン1.3に基づいて、デイブ・ベンハムによって書かれ、もともとRead key presses via REPLACE - New functions :getKey, :getAnyKey, :getMaskedInput

もっと複雑なバッチに掲載が、コンセプトの証明としては、CTRL + Cを区別して入力します。

@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 
+0

この解決策の唯一の欠点は、コピー&ペーストからの入力を受け取ることができないことです。一つの文字を読み込んだ後に 'replace'が入力バッファをクリアするように見えるからです。 – jeb

+0

@jeb Right。あなたが気づいたように、 'errorlevel'チェックでさえ失敗し、' CTRL + C'のために1にセットされ、空の入力にもセットされます。だから誰の味にも雨が降らない。私は 'CTRL + C'と' ENTER'が区別できるかどうかをチェックしようとしていました。ところで、CTRL + Cのキャプチャが何とか働くようになったのは初めてです。 – elzooilogico

関連する問題