您的假设是错误的,即执行从文件 two.bat 返回,因为只有当您使用 call command1 时才会出现这种情况。
批处理文件 one.bat 在括号中的代码块中运行 two.bat,该代码块已经在命令堆栈2 中,因此该块在终止执行之前(有点)完成。
你的输出完美地说明了发生了什么(因此我在这里评论它):
J:\>one
1 2 /* first loop iteration, the first `echo %%i !j!` in the block is
executed as expected; */
Hello World /* `two.bat` is run; execution does NOT return to `one.bat`,
because there is NO `call`, which would put a return point onto
the stack! the only thing remembered and thus accomplished is
the current command line or parenthesised block; */
1 !j! /* the second `echo %%i !j!` in the block is executed as it is
still buffered, but `two.bat` is already quit, hence implicit
`endlocal` commands have been executed, so all the nested
`setlocal` commands in your scripts are cancelled and delayed
expansion is disabled (default state); moreover, variable `j` is
no longer defined here; */
/* at this point, the parenthesised block, which is the loop body,
has been executed, hence batch file context is left and Command
Prompt context applies, so `@echo off` from `one.bat` does no
longer apply here; */
J:\>( // this block is nothing but the echo of the second loop iteration,
set j=2 // which is still buffered;
set /A j=!j! + 1
echo 2 !j!
two.bat
echo 2 !j!
)
Missing operator. /* this error message is caused by the attempt to execute
`set /A j=!j! + 1` (remember that delayed expansion is no longer
enabled and `j` is undefined); */
2 !j! // first `echo %%i !j!` in the buffered second loop iteration;
Hello World /* `two.bat` is run again; afterwards, batch file context is left
again and Command Prompt context applies; */
2 !j! // second `echo %%i !j!` in the buffered second loop iteration;
要证明执行是在批处理文件还是命令提示符上下文下,只需将set /A j作为最后一个命令放在one.bat的循环体中,这样您将在输出1 !j!之后得到额外的输出0第二个2 !j!,因为set /A 在批处理文件上下文中不返回任何内容,但它在命令提示符上下文中输出(最后一个)结果(没有尾随换行符); 0 的值表明 j 不再设置。
1) 有几个例外:被调用的批处理文件涉及到管道,或者被for /F loop 运行和解析,因为批处理文件在这样的新cmd.exe 实例中运行
2) 如果调用的批处理文件包含在具有串联命令的行中,情况也是如此,因此在执行two.bat 时,two.bat & echo Fine 之类的内容会回显Fine .