Echo out of nowhere

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Echo out of nowhere

#1 Post by Liviu » 12 Sep 2012 18:40

Must be one of those days when strange (cmd) things just keep piling up ;-)

It's been known that for/l loops run in their own special "mode", and can't be really broken out of short of a hard "exit". Maybe related, here is another peculiar for/l behavior. Using the following two batch files...

Code: Select all

:: for-l.cmd
@echo off
echo ^>^>^>
for /l %%n in (1,1,3) do echo-one %%n
echo ^<^<^< &rem never reached

Code: Select all

:: echo-one.cmd
@echo off
echo [%0]: %*
...and running "for-l.cmd" gives the following.

Code: Select all

C:\tmp>for-l
>>>
[echo-one]: 1

C:\tmp>echo-one 2
[echo-one]: 2

C:\tmp>echo-one 3
[echo-one]: 3

Note the two "C:\tmp>echo-one" lines. It's as if, after the first iteration, echo gets turned back on. No idea how or why, but the behavior is consistent.

Liviu

jeb
Expert
Posts: 1062
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: Echo out of nowhere

#2 Post by jeb » 13 Sep 2012 00:32

Try CALL :D

You simply stop the batch file with your echo-one.bat file, you forgot to use CALL.
Normally this stops the parenof t batch, but in this case the FOR/L is cached and the cached context will be finished, but not the rest of the FOR-L.CMD

That's also the cause why ECHO ON is enabled again after the first invoke.

jeb

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: Echo out of nowhere

#3 Post by Liviu » 13 Sep 2012 09:13

jeb wrote:you forgot to use CALL.

Normally this stops the parenof t batch, but in this case the FOR/L is cached and the cached context will be finished, but not the rest of the FOR-L.CMD

Of course, but the point of the exercise was _not_ using CALL ;-) Yes, the rest of FOR-L won't be executed, as my comment "rem never reached" recognized. However, I am still a bit surprised as to how the for/l loop is "cached".

jeb wrote:That's also the cause why ECHO ON is enabled again after the first invoke.

This is the part which was/is not clear to me. You seem to be right, and the iterations past the first one, however/wherever they might be cached, but no longer run in the context of the calling batch file. The modified for-l.cmd below verifies that local variables and the delayed expansion setting are also lost on the 2nd and 3rd iterations.

Code: Select all

:: for-l.cmd
@echo off
setlocal enableDelayedExpansion
set "localVar=--- "
echo ^>^>^>
for /l %%n in (1,1,3) do (<nul call set/p"=%%localVar%%") & echo-one %%n --- !time!
echo ^<^<^< &rem never reached
Output.

Code: Select all

C:\tmp>for-l
>>>
--- [echo-one]: 1 --- 10:07:45.59

C:\tmp>(call set/p"=%localVar%" 0<nul )  & echo-one 2 --- !time!
%localVar%[echo-one]: 2 --- !time!

C:\tmp>(call set/p"=%localVar%" 0<nul )  & echo-one 3 --- !time!
%localVar%[echo-one]: 3 --- !time!

Liviu

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Echo out of nowhere

#4 Post by dbenham » 13 Sep 2012 10:00

I answered a similar question on StackOverflow recently. My answer was basically the same as jeb's - The batch context terminates (and the ECHO state is restored to ON) once the 2nd batch file ends, but the cached FOR loop continues to execute.

As you can see from the linked SO question, the behavior occurs with all forms of FOR, not just FOR /L. In fact, the behavior will occur with any cached group of commands that executes a batch script without using CALL.

test.bat

Code: Select all

@echo off
prompt $g
set var=before
setlocal enableDelayedExpansion
set var=after
(
  for %%a in (1) do echo Start out in batch context
  echo var=!var!
  test2 Batch context ends once this command finishes
  for %%a in (1) do echo Now in command context
  echo var=!var!
  call echo var=%%var%%
)
echo This command is not reached

test2.bat

Code: Select all

@echo off
echo %*

Results of running test.bat

Code: Select all

Start out in batch context
var=after
Batch context ends once this command finishes

>echo Now in command context
Now in command context
var=!var!
var=before

>


Dave Benham

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: Echo out of nowhere

#5 Post by Liviu » 13 Sep 2012 17:52

dbenham wrote:I answered a similar question on StackOverflow recently. My answer was basically the same as jeb's - The batch context terminates (and the ECHO state is restored to ON) once the 2nd batch file ends, but the cached FOR loop continues to execute.

Thanks for the link. To be pedantically precise, I'd say that the "current batch file context" terminates. In case the current context was a call'd label in the top batch file, control returns to the parent context in the caller, not necessarily the command line context. For example, the following works

Code: Select all

@echo off
echo ^>^>^>
for /l %%n in (1,1,3) do call :one %%n
echo ^<^<^<
goto :eof

:one
(
 echo-one %~1
)
goto :eof &rem never reached
and outputs

Code: Select all

>>>
[echo-one]: 1
[echo-one]: 2
[echo-one]: 3
<<<


If one wonders why the parantheses around the 'echo-one' line, that's related to the entertaining thread at viewtopic.php?f=3&t=2851.

Liviu

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Echo out of nowhere

#6 Post by dbenham » 13 Sep 2012 19:01

Liviu wrote:To be pedantically precise, I'd say that the "current batch file context" terminates. In case the current context was a call'd label in the top batch file, control returns to the parent context in the caller, not necessarily the command line context.

No need for the adverb - that is an important point. :D

I had forgotten about that thread you referenced - it is entertaining :)

You forgot to include the definition of echo-one.bat. I presume it is something like the following:

Code: Select all

@echo [%0]: %1

Your example might be a bit more demonstrative if the last line is changed to echo This line is never reached. The GOTO :EOF (or EXIT /B) is not needed at the end because the subroutine ends as soon as echo-one is invoked without a CALL.


Dave Benham

edwardmaya
Posts: 1
Joined: 13 Sep 2012 23:23

Re: Echo out of nowhere

#7 Post by edwardmaya » 13 Sep 2012 23:28

You stop the set pc computer file with your echo-one.bat pc computer file, you ignored to use CALL.
Normally this stops the parenof t set, but in this situation the FOR/L is cached and the cached viewpoint will be finished, but not the rest of the FOR-L.CMD

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: Echo out of nowhere

#8 Post by Liviu » 14 Sep 2012 00:59

dbenham wrote:You forgot to include the definition of echo-one.bat. I presume it is something like the following:

Almost right, mine (in the first post) was actually one line longer ;-)

Liviu

P.S. @edwardmaya, if you read the entire thread, _not_ using CALL was the premise of the discussion and, yes, the "terminating" behavior of "chaining" a batch file directly was well understood.

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Echo out of nowhere

#9 Post by foxidrive » 14 Sep 2012 02:03

Liviu wrote:P.S. @edwardmaya


FWIW that poster reproduced this post almost verbatim. It could be a spammer 'getting his foot in the door'.

viewtopic.php?p=20035#p20035

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: Echo out of nowhere

#10 Post by Liviu » 14 Sep 2012 08:21

...or a bot, since the gibberish looks like possibly a (naive) English-to-some-other-language-and-back-to English automatic translation, though I couldn't figure out which such roundtrip would match "forget" to "ignore" and "context" to "viewpoint" ;-)

Post Reply