3

I am using the following code to benchmark my script.

C:\Users\blueray>echo %time% & timeout /t 5 & echo %time%

Output

13:44:44.64
... after 5 seconds
13:44:44.64

I was expecting to have a 5 second increment when I echo %time% for the second time. What is the problem here and what is the solution?

blueray
  • 6,268
  • 2
  • 25
  • 46

3 Answers3

2

A workaround

(for /F "delims=" %x in ('echo ^%time^%') do echo %x )& timeout /t 2 &(for /F "delims=" %x in ('echo ^%time^%') do echo %x)
Nahuel Fouilleul
  • 16,821
  • 1
  • 26
  • 32
  • Running each `echo %time%` in a background command process started by __FOR__ using `cmd.exe /C`, capturing their outputs by __FOR__ and output the captured time output in current command process seems to be a quite difficult to use and understand workaround although working fine. There are easier solutions as I wrote in my answer on this question. – Mofi Feb 06 '18 at 11:27
1

Windows command interpreter first preprocesses/parses the entire command line before execution. During this preprocessing all environment variable references in the form %variable% are expanded so that in your case the command line really executed is:

echo 13:44:44.64   & timeout /t 5   & echo 13:44:44.64

It is necessary to force a delayed expansion of the environment variables.

Usually delayed expansion is used in a batch file like this:

setlocal EnableDelayedExpansion
echo !TIME! & timeout /t 5 & echo !TIME!
endlocal

Or on specifying executable TIMEOUT with fully qualified file name and using immediate environment variable expansion on first TIME reference while using delayed expansion on second TIME reference:

setlocal EnableDelayedExpansion
echo %TIME% & %SystemRoot%\System32\timeout.exe /t 5 & echo !TIME!
endlocal

But there is a second method to get a delayed environment variable expansion in a batch file by using the command CALL.

echo %TIME% & %SystemRoot%\System32\timeout.exe /t 5 & call echo %%TIME%%

This command line in batch file results in executing finally the command line:

echo 13:44:44.64   & C:\Windows\System32\timeout.exe /t 5   & call echo %TIME%

The command CALL results in a second parsing of echo %TIME% before executing second ECHO resulting in getting output time about 5 seconds later than first time output.

In a command prompt window a different command line is required due to different interpreting of % in comparison to batch file processing.

echo %TIME% & timeout /t 5 & call echo ^%TIME^%

The percent sign characters are escaped with caret character ^ to be first interpreted as literal characters to finally execute call echo %TIME%. In real it is enough to escape just second % while escaping just first % has not the wanted effect on time output. So working in a command prompt window as expected is also:

echo %TIME% & timeout /t 5 & call echo %TIME^%

But not working as expected in a command prompt window is:

echo %TIME% & timeout /t 5 & call echo ^%TIME%
Mofi
  • 38,783
  • 14
  • 62
  • 115
  • The code works fine but I did not understand the last part. Why ^%TIME^% and %TIME^% works but ^%TIME% dont – blueray Feb 06 '18 at 12:21
  • 1
    @blueray I asked that myself too. I don't have a real explanation. I think the character `^` is simply just ignored and removed from command line by `cmd.exe` __after__ expanding the environment variable references according to answer on [How does the Windows Command Interpreter (CMD.EXE) parse scripts?](https://stackoverflow.com/questions/4094699/) So `^%TIME%` does not work because `^` is in real ignored because not really escaping `%` and so `%TIME%` is expanded first. Later `^` is removed from the command line. On usage of `%TIME^%` the environment variable expansion first fails. – Mofi Feb 06 '18 at 14:13
0

Once the command line is read, %time% is changed to its value and then the command is executed.

All env args %arg% change before command line execution.

In script: When the script is read it executes line after line. In that case your value will be different.

IQV
  • 492
  • 6
  • 14
shaiki siegal
  • 424
  • 3
  • 9