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



我整理了一个供最终用户使用的批处理脚本。除了让用户认为发生了什么之外,没有特定的功能目的,我想让脚本等待几秒钟,然后再继续执行。在 Vista 及更高版本上,这可以通过TIMEOUT /3轻松实现。

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

TIMEOUT所做的只是从你给它的时间t一直算到0。因此,您实际上可以通过执行以下操作来执行相同的操作:

  1. 打印一些东西(如果需要,可以带t)
  2. 等待 1 秒
  3. 打印一些东西(带t-1)
  4. 等待 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

它只覆盖直到 o 的go,所以X seconds to go...的尾随点...仍然可见,你最终会得到

Done waiting......

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

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

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

我还要感谢@LotPing,他的回答让我意识到你实际上可以像他一样用FOR /L替换从标签:ONE_SECIF...goto ONE_SEC的所有东西:

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
)

我替换了等待的"不太稳定"timeouttimeout /N将等待N-1N秒,对于大N来说是可以的,但N=1可能会导致一些问题。(例如,等待 0.3 秒而不是 1 秒的效果与 149.3 而不是 150 不同)。 我不需要循环前的额外set /p

我没有看到问题,您可以抑制暂停输出

Echo My own hint to press any key
Pause >NUL

您可以使用超时。

向 J.Baoby 致敬 对于卡雷特,倒计时循环比手动循环简单一些。
循环中的第一组/P 似乎没有回响 nummber——所以我把一个放在前面。

@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...

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

最新更新