6

Supposing there is a batch file (caller) which executes another batch file (callee), the call command needs to be used in order to return to the caller after the callee finishes execution. Here is an example:

caller.bat:

echo Calling another script...
call callee.bat
echo Returned from callee...

callee.bat (in the same location):

echo   Being called from caller...

The output will be this (omitting the command echos), showing that execution returned as expected:

Calling another script...
  Being called from caller...
Returned from callee...

If the call command was dismissed in the caller, the output would be:

Calling another script...
  Being called from caller...

But as soon as the callee is involved in a pipe (|), there is no difference in whether or not the call command is used. For instance:

caller.bat (the callee remains unchanged):

echo Calling another script...
break | callee.bat
echo Returned from callee...

The output will be this, although there is no call command.

Calling another script...
  Being called from caller...
Returned from callee...

What is the reason for this behaviour, what causes execution to return to the caller here?

aschipfl
  • 33,626
  • 12
  • 54
  • 99
  • 1
    The question for me is there any difference between `break|command` and `call command` ? Check also this `set a=b` ; `set b=c` ; `break|echo %%%a%%%` . And... the output is `c` .In both cases you create a new sub-context of the cmd. May be some states of the cmd preserved when `call` is used ? – npocmaka Mar 18 '16 at 23:32
  • 1
    Oh. `REM` , `IF` and `FOR` behave different when are piped and when are CALLed but this is rahter die to the parsing. – npocmaka Mar 18 '16 at 23:38
  • Hmm... besides data transfer of _STDOUT_ to _STDIN_ of pipes, there seems to be no difference at all; even `cmd /C callee.bat` returns to the caller; yes, `rem`, `if` and `for` are special, because I remember they are recognised earlier than other commands during the parsing process... – aschipfl Mar 18 '16 at 23:40
  • I think it has to do with the way cmd parses stuff, first parsing the entire line, and then executing the piped commands, effectively parsing them a second time. – Dennis van Gils Mar 18 '16 at 23:43
  • 4
    related: http://stackoverflow.com/a/8194279/5022761 – Dennis van Gils Mar 18 '16 at 23:51

1 Answers1

6

There are two ways to call another Batch file from the caller one (main file): call callee.bat and cmd /C callee.bat; the difference is that call execute the other Batch file in the same context of the caller program, so they share the same environment variables and another status, whereas cmd /C execute the other Batch file in an entirely separated context. Just as a personal note, I used to name internal subroutine the Batch file invoked via call, and external subroutine the one invoked via cmd /C (and overlay the Batch file directly invoked without call nor cmd /C, that inherits the behavior and context of the caller Batch file).

In the execution of a pipe, both sides of the pipe are executed via a cmd /C, so both sides are invoked as external subroutines. This way, if any side of a pipe is a Batch.BAT file, it returns to the caller program when it ends.

The same behavior happen in a callee Batch file placed in a for /F command, and exaclty for the same reason; for /F %%a in ('calle.bat') do ...

Aacini
  • 65,180
  • 12
  • 72
  • 108