复制CMD"超时"倒计时打印在自定义回显中

时间:2016-12-21 21:42:28

标签: windows batch-file for-loop cmd

我已经整理了一个供最终用户使用的批处理脚本。除了让用户认为某些事情正在发生之外没有特定的功能目的,我想让脚本在继续执行之前等待几秒钟。在Vista及更高版本中,可以使用TIMEOUT /3轻松完成此操作。

但是,我想用自己的自定义输出替换TIMEOUT命令的默认输出,同时保留其倒计时功能。据我所知,TIMEOUT或等效的PINGSLEEP方法支持此功能,因此必须手动完成,我想知道是什么最简单的方法来完成它是。

2 个答案:

答案 0 :(得分:7)

所有TIMEOUT确实从你给它的时间t开始计算,等到0。所以你可以通过以下方式实现同​​样的目的:

  1. 打印一些内容(如果需要,可以使用t
  2. 等一下
  3. 打印某些内容(使用t-1
  4. 等一下 ...
  5. 您可能想要在一行上打印所有内容。您可以通过在一行末尾打印一个回车来实现:效果将是您将能够覆盖该行(该内容将被完全删除,但只是被覆盖)。这是一个获得回车字符并启用延迟扩展的技巧:

    FOR /F %%a IN ('copy /Z "%~dpf0" nul') DO set "carret=%%a"
    

    这会将回车符放在carret变量中。

    现在打印...您无法使用echo进行打印,它仍然会以回车符和换行符结束每个输入(您将结束)在每个echo之后的新行上,并且回车将不再有用)。因此,您必须使用set /p。它允许您在没有回车和换行符的情况下进行打印:set /p =print something<nul

    所以你的批次看起来像这样:

    @echo off
    SetLocal EnableDelayedExpansion
    
    REM countdown of 5 seconds
    set count=5
    
    REM prepare carriage return
    FOR /F %%a IN ('copy /Z "%~dpf0" nul') DO set "carret=%%a"
    
    :ONE_SEC
    REM print message
    set /p =%count% seconds to go...!carret!<nul
    REM wait one sec
    ping -n 2 127.0.0.1 > nul 2>&1
    REM decrement
    set /a count-=1
    IF %count% GTR 0 goto :ONE_SEC
    
    REM last print, now you can use echo but don't forget: you have to override each character of the previous print! so fill all remaining place with whitespaces
    echo Done waiting...   
    REM  X seconds to go...
    
    EndLocal
    exit /b 0
    

    编辑:因为回车只允许覆盖之前打印的行,如果回车后打印的内容不能完全覆盖什么,则必须添加空格以前打印过。这是最后一个echo所发生的情况:Done waiting...X seconds to go...短,所以它不会完全覆盖它:

    Done waiting...   
    X seconds to go...
       from here ->   <- untill here: characters that won't be overwritten
    

    它仅覆盖go的o,因此...的尾随点X seconds to go...仍然可见,您最终会

    Done waiting......
    

    解决方案是使用空格(3个超过字符 - > 3个空格)覆盖那些超出字符的字符。所以最后的回声应该是

    echo Done waiting...<SPACE><SPACE><SPACE>
    

    <SPACE>替换为真实的空格。我在上面的代码中也添加了它,但它不可见。

    另外,我还要感谢@LotPing answer让我意识到您实际上可以用{:ONE_SEC替换IF...goto ONE_SECFOR /L的所有内容1}}就像他做的那样:

    FOR /L %%S IN (%count%, -1, 1) DO (
        set /p =%%S seconds to go...!carret!<nul
        ping -n 2 127.0.0.1 > nul 2>&1
    )
    

    我取代了不太稳定的&#34; timeout等待。 timeout /N会在N-1N秒之间等待,对于大型N会有效,但N=1会导致一些问题。 (等待0.3秒代替1的效果与149.3而不是150例如不同)。 我不需要在循环之前的额外set /p

答案 1 :(得分:1)

我没有看到问题,你可以用

来抑制暂停输出
Echo My own hint to press any key
Pause >NUL

你可以做超时。

对于Carret来说,向J.Baoby致敬,倒计时循环比手动循环更简单。
循环中的第一组/ P似乎没有回显数字 - 所以我把它放在前面。

@Echo off&SetLocal EnableExtensions EnableDelayedExpansion

REM countdown of 5 seconds
set /A count=15

REM prepare carriage return
FOR /F %%a IN ('copy /Z "%~dpf0" nul') DO set "carret=%%a"

set /p =%count% seconds to go...!carret!  <nul
For /L %%S in (%Count%,-1,1) Do (
  set /p =%%S seconds to go...!carret!  <nul
  Timeout /T 1 >NUL
)
echo Done waiting...

要提示更长的倒计时,不要在某些空格后面留下字符,应添加到提示的末尾。为了能够中断倒计时,您可以选择交换超时并在循环中检查错误级别。