我已经整理了一个供最终用户使用的批处理脚本。除了让用户认为某些事情正在发生之外没有特定的功能目的,我想让脚本在继续执行之前等待几秒钟。在Vista及更高版本中,可以使用TIMEOUT /3
轻松完成此操作。
但是,我想用自己的自定义输出替换TIMEOUT
命令的默认输出,同时保留其倒计时功能。据我所知,TIMEOUT
或等效的PING
或SLEEP
方法支持此功能,因此必须手动完成,我想知道是什么最简单的方法来完成它是。
答案 0 :(得分:7)
所有TIMEOUT
确实从你给它的时间t
开始计算,等到0。所以你可以通过以下方式实现同样的目的:
t
)t-1
)您可能想要在一行上打印所有内容。您可以通过在一行末尾打印一个回车来实现:效果将是您将能够覆盖该行(该内容将被完全删除,但只是被覆盖)。这是一个获得回车字符并启用延迟扩展的技巧:
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_SEC
到FOR /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-1
和N
秒之间等待,对于大型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...
要提示更长的倒计时,不要在某些空格后面留下字符,应添加到提示的末尾。为了能够中断倒计时,您可以选择交换超时并在循环中检查错误级别。