为啥调用嵌套批处理文件而不在行前添加“调用”退出父批处理文件?
Posted
技术标签:
【中文标题】为啥调用嵌套批处理文件而不在行前添加“调用”退出父批处理文件?【英文标题】:Why does calling a nested batch file without prepending "call" to the line exit the parent batch file?为什么调用嵌套批处理文件而不在行前添加“调用”退出父批处理文件? 【发布时间】:2012-07-23 05:36:43 【问题描述】:我了解如何使用call
命令从父文件中调用嵌套批处理文件,因为这方面有很多资源:
但是,我不明白为什么从另一个调用另一个批处理文件会终止父级。
举一个不太抽象的例子,假设我有一个批处理文件将单独的批处理文件“链接”在一起,而我错误地没有在每一行前面加上 call
:
foo.bat
bar.bat
这只会执行 foo.bat 然后退出。要正确执行这两个命令,我必须在每个语句之前添加 call:
call foo.bat
call bar.bat
为什么第一个功能仍然存在?怎么还没改?我注意到call
是在 1980 年代后期发布的 MS-DOS 3.3 中引入的,那么这个功能是否仍然存在以实现反向兼容?
我想不出它的任何(实际)用途,但也许我太习惯于“新”编程技术了。
【问题讨论】:
Why does only the first line of this Windows batch file execute but all three lines execute in a command shell? 的可能重复项 【参考方案1】:DOS 使用简单的文本处理(当您在 config.sys 中有类似 FILES=20
的东西以允许 20 文件句柄时),所以打开文件,读取下一行,关闭文件,然后执行刚刚读取的行。如果该文件调用了另一个文件,则该文件继续处理,因此批处理文件只需要一个文件句柄。
直到微软输入call
命令,没有办法回到原始文件(不使用诸如将前一个文件的名称作为参数,以及使用临时文件让原始批处理文件知道它有一些处理,然后可以GOTO
文件的下一部分)。
【讨论】:
好的,所以最初的功能只是被忽略了?call
的实施是因为人们通常使用您所描述的解决方法?他们不会仅仅为了向后兼容而覆盖初始功能吗?
正确。向后兼容性是允许许多 win 3.0 程序仍然在 win 7 上运行的原因。当时,我最终在汇编程序中编写了一些函数,以便它成为一个程序并且可以返回到批处理文件 - 现在是 @987654325 @,我使用一个简单的程序来实现,该程序将错误级别设置为按下字符的 ASCII 值。
顺便说一句,读取一行、执行它、读取另一行等功能意味着您可以拥有自修改批处理文件。我从来没有故意这样做过——但如果你有一个批处理文件从修订控制中检索自身(新版本),你会得到奇怪的结果,它执行版本 1 直到执行检索的行,然后继续使用第 2 版。【参考方案2】:
正如 Sean Cheshire 所写,向后兼容是必要的。
但不使用CALL
从批处理文件启动批处理文件不会终止父级!
看起来是这样,因为在第二批退出后,父级通常不会进一步执行。
但是在启动 second.bat 之前使用调用会显示第一批没有终止。
parent.bat
echo parent.bat
call :myLabel
echo back in parent.bat main
exit /b
:myLabel
second.bat & echo back in parent.bat
exit /b
second.bat
echo second.bat
exit /b
我在这里使用secpond.bat & echo back ...
来避免cmd.exe 的另一个错误/功能。
如果您使用 second.bat
而不使用任何附加功能,它将开始 second.bat
AND 跳转到标签 :myLabel
in second.bat
!
【讨论】:
我会注意到/B
是在 NT 4 中引入的 - 在此之前,只有可怕的编程技巧可用【参考方案3】:
Call
基本上是在说“去执行这个另一个批处理文件,然后回到这里继续”。它从 DOS 3.3 左右就已经存在,如果现在将其删除,将破坏所有向后兼容性(这就是人们仍在使用批处理脚本的原因)。它还可以用于分支到:link
位置。
有关使用和语法的信息(供其他人将来参考),您可以查看此MS TechNet link
如果您需要新功能,请改用 CMD 脚本或 PowerShell 脚本。
【讨论】:
感谢您的回答,但这并不是我要问的。您还复制了我在问题中提供的一些信息。我了解call
的工作原理,并且有很多不了解的人可以参考。我想知道何时在批处理脚本中实际使用另一种方式(不使用call
)。如果批处理文件嵌套在另一个批处理文件中,为什么有人希望父级停止?
因为维护你离开的地方的堆栈会增加你的常驻内存段大小,这会限制可以运行的程序的最大大小。一旦做出该决定,就无法更改,因为它会使现有的批处理文件停止工作。以上是关于为啥调用嵌套批处理文件而不在行前添加“调用”退出父批处理文件?的主要内容,如果未能解决你的问题,请参考以下文章
为啥这个父类 setter 调用使用 type(self) 而不是 self?
React Native - 处理来自子组件(自定义组件)的父状态,而不在父组件中添加功能
为啥这个 for 循环在某些平台上退出而不在其他平台上退出?