0

Lets say if I have to print time and date three times, I have to write

echo %date% %time%
echo %date% %time%
echo %date% %time%

The above code prints three different times, if I assign %date% %time% to a variable (to avoid writing them each time) then it is printing constant value three times,

set a=%date%_%time%
echo %a%
echo %a%
echo %a%

I however want to create the %a% variable once, and still echo the actual date and time as they change.

Gerhard
  • 22,678
  • 7
  • 27
  • 43
pasha
  • 2,035
  • 20
  • 34
  • In the second block of code all the echos are generating same value, i.e., the variable is set to static value, I want each of the echo to print different value as %time% changes – pasha Aug 17 '18 at 11:27

4 Answers4

5

It's possible with delayed expansion:

@echo off
setlocal enabledelayedexpansion
set  "a=^!time^!"
echo %a%
timeout 2 >nul
echo %a%

Often call is used for a second layer of parsing to avoid delayed expansion (like in aschipfl's answer), but to use it exactly like any other variable, delayed expansion is the only way to do it.

If for any reason you have to have delayed expansion disabled or want it to work directly on command line, the call method is a good alternative, when you don't mind to type the additional call command.

Stephan
  • 53,940
  • 10
  • 58
  • 91
  • I completely forgot about doing that without needing the loop! Best answer on this for sure :) – Gerhard Aug 17 '18 at 11:50
  • I just copied this code to a .bat file and running it is giving me, "ERROR: Invalid syntax. Default option is not allowed more than '1' time(s). Type "TIMEOUT /?" for usage." – pasha Aug 17 '18 at 11:55
  • running it in command line prints !time! and not actual time, I'm not sure what I'm doing wrong – pasha Aug 17 '18 at 11:58
  • try to remove the `/t` (depends on your OS) or use any other command that consumes some time. / There is no delayed expansion on commandline (outside of batchfiles) by default. See `cmd /?` to how to enable it. – Stephan Aug 17 '18 at 12:00
  • 1
    Enable delayed expansion in command prompt by starting it with `cmd /V`... – aschipfl Aug 17 '18 at 13:16
  • and to add to @aschipfl comment, I think it is worth mentioning `cmd /V:OFF` to disable it. – Gerhard Aug 17 '18 at 13:24
  • @GerhardBarnard `cmd /v` will start a second process with delayed expansion enabled. Rather than starting a third process with delayed expansion disabled, just `exit` the second one to get back to the first one. – Stephan Aug 17 '18 at 13:35
  • @Stephan yes, that I know, but does OP know that? Hence mentioning the `/V:ON` and `/V:OFF` switches. – Gerhard Aug 17 '18 at 13:56
2

What about this in a batch file:

set "a=%%date%% %%time%%"

call echo %a%
> nul timeout 1
call echo %a%
> nul timeout 1
call echo %a%

In command prompt it looks like this:

>>> set "a=%^date% %^time%"
>>> call echo %a%
>>> call echo %a%
>>> call echo %a%
aschipfl
  • 33,626
  • 12
  • 54
  • 99
1

I am assuming you want to set a once, but still show the actual changes in the date and time?

@echo off
setlocal enabledelayedexpansion
for %%i in (1,1,3) do (
        set a=!date!_!time!
        timeout /t 1 > nul
        echo !a!
)

I have used timeout to simply show the difference in time because it runs so quick, it will display the same time as it runs within milliseconds.

Alternatively, call a label:

@echo off
for %%i in (1,1,3) do (
call :timeloop
)
goto :eof
:timeloop
set a=%date%_%time%
timeout /t 1 > nul
echo %a%

you can call the label witihout a loop as well:

@echo off
echo do something
call :timeloop
echo do something else
call :timeloop
goto :eof
:timeloop
set a=%date%_%time%
timeout /t 1 > nul
echo %a%
Gerhard
  • 22,678
  • 7
  • 27
  • 43
  • Yes I want to set 'a' once to %time% and have its value changed as %time% changes without resetting. But in above code you are setting 'a' each time the for loop body is getting executed, right? (Also could you please edit my question so that it'd be clear, I'm afraid that if I edit it, it'll become a lot less clear) – pasha Aug 17 '18 at 11:36
  • Thank you for editing. Below answer from Julio is what I was looking for, i.e., we cannot do this and the code provided in that answer is of good use for me. So, I have to accept Julio's answer. – pasha Aug 17 '18 at 11:47
  • Actually I just tried, @aschipfl's answer and it works – pasha Aug 17 '18 at 12:03
  • I just tried the answers one after the other and my bad luck was that I tried the best one last. I'm not sure what "setlocal enabledelayedexpansion" would do to my other part of the script. And since aschipfl's answer didn't use anything cryptic (to me), I think it is the best way of doing what the question specifies. I just want the best answer for the question to be marked as accepted, since my level of knowledge in batch scripting is limited to only ctrl+c & ctrl+v, could you please let me know if Stephan's answer is the better than aschipfl's. – pasha Aug 17 '18 at 12:33
  • `setlocal /?` will help you understand `delayedexpansion` – Gerhard Aug 17 '18 at 12:45
  • 1
    @pasha: there are good reasons to use one, and there are good reasons to use the other. I added a bit of decision aid to my answer. You are supposed to accept the answer that works best *for you* (don't care to decide which would be the best answer for others). The "best" answer in academic view will be rewarded by upvotes. – Stephan Aug 17 '18 at 12:47
  • @Stephan, I didn't exactly put what I wanted in the question, so it created a difference in what is the best answer for the question and what I wanted. I'll try to be more specific in future. Thanks for the answer BTW. – pasha Aug 17 '18 at 12:59
1

You may use this as an alternative:

@echo off

call :printdate
REM here I wait 2 seconds to test different timestamp values
timeout 2 1>NUL
call :printdate

pause
exit /B 0

:printdate
echo The timestamp is: %DATE%-%TIME%
goto :eof

Output:

The timestamp is: 17/08/2018-13:40:10,37
The timestamp is: 17/08/2018-13:40:12,16

If you want to pass a parameter, use this:

@echo off

call :printdate "The OLD timestamp is: "
REM here I wait 2 seconds to test different timestamp values
timeout 2 1>NUL
call :printdate "The NEW timestamp is: "

pause
exit /B 0

:printdate
echo %~1 %DATE%-%TIME%
goto :eof

Output:

The OLD timestamp is:  17/08/2018-13:54:46,24
The NEW timestamp is:  17/08/2018-13:54:48,14
Julio
  • 5,208
  • 1
  • 13
  • 42
  • Thank you Julio, the code is very useful for me, I can pass a string as an argument to the routine and print that along with date and time (I mentioned this comment so that anyone looking at this can know that you can pass arguments to routine) – pasha Aug 17 '18 at 11:53
  • Sure, I added an example on my answer. I'm glad It did the trick for you. – Julio Aug 17 '18 at 11:56
  • answer provided by aschipfl works, it is possible to create what I wanted. Your answer is a lot helpful to me but the answer provided by aschipfl is right for this question, apologies but I have to accept his answer. – pasha Aug 17 '18 at 12:06
  • No problem! I changed the title of my answer just to provide it as an alternative. I also upvoted Stephan 's answer – Julio Aug 17 '18 at 12:17