如何在. BAT文件中运行多个. BAT文件

我正在尝试让我的commit-build.bat执行其他。BAT文件作为我们构建过程的一部分。

commit-build.bat的内容:

"msbuild.bat""unit-tests.bat""deploy.bat"

这看起来很简单,但commit-build.bat只执行列表中的第一项(msbuild.bat)。

我已经分别运行了每个文件,没有任何问题。

1058137 次浏览

用途:

call msbuild.batcall unit-tests.batcall deploy.bat

当不使用CALL时,当前批处理文件停止并被调用的批处理文件开始执行。这是一种可以追溯到早期MS-DOS时代的特殊行为。

尝试:

call msbuild.batcall unit-tests.batcall deploy.bat
call msbuild.batcall unit-tests.batcall deploy.bat

要在.bat文件中调用.bat文件,请使用

call foo.bat

(是的,这很愚蠢,如果你可以用foo.bat调用它会更有意义,就像你可以从命令提示符中调用它一样,但正确的方法是使用call

看看你的文件名,你有没有考虑过使用像Nant或ant(Java版本)这样的构建工具。

所有其他答案都是正确的:使用call。例如:

 call "msbuild.bat"

历史

在古老的DOS版本中,不可能递归执行批处理文件。然后引入调用命令,调用另一个cmd shell来执行批处理文件,并在完成后将执行返回给调用cmd shell。

显然,在以后的版本中,不再需要其他cmd shell。

在早期,许多批处理文件依赖于调用批处理文件不会返回到调用批处理文件的事实。在没有额外语法的情况下改变这种行为会破坏许多系统,例如批处理菜单系统(使用批处理文件作为菜单结构)。

与Microsoft的许多情况一样,向后兼容性是这种行为的原因。

Tips

如果批处理文件的名称中有空格,请在名称周围使用引号:

call "unit tests.bat"

顺便说一句:如果您没有批处理文件的所有名称,您也可以使用for来执行此操作(它不保证批处理文件调用的正确顺序;它遵循文件系统的顺序):

FOR %x IN (*.bat) DO call "%x"

您也可以在呼叫后对错误级别做出反应。使用:

exit /B 1   # Or any other integer value in 0..255

返回错误级别。0表示正确执行。在调用批处理文件中,您可以使用

if errorlevel neq 0 <batch command>

如果您的Windows比NT4/2000/XP旧,请使用if errorlevel 1来捕获所有错误级别1及更高。

要控制批处理文件的流程,有goto:-(

if errorlevel 2 goto label2if errorlevel 1 goto label1...:label1...:label2...

正如其他人所指出的:看看构建系统来替换批处理文件。

您正在调用多个批处理以编译程序。我理所当然地认为,如果发生错误:
1)批处理中的程序将以错误级别退出;
(2)你想知道吗?

for %%b in ("msbuild.bat" "unit-tests.bat" "deploy.bat") do call %%b|| exit /b 1

'||'测试高于0的错误级别。这样,所有批处理都按顺序调用,但会在任何错误时停止,让屏幕保持原样以供您查看任何错误消息。

如果我们想打开多个命令提示符,那么我们可以使用

start cmd /k

/k:是强制执行的。

启动许多命令提示符可以如下所示。

start cmd /k Call rc_hub.bat 4444
start cmd /k Call rc_grid1.bat 5555
start cmd /k Call rc_grid1.bat 6666
start cmd /k Call rc_grid1.bat 5570.

在一个脚本中运行多个脚本我遇到了同样的问题。我一直让它在第一个脚本上死亡,而没有意识到它在第一个脚本上退出。

:: OneScriptToRunThemAll.batCALL ScriptA.batCALL ScriptB.batEXIT
:: ScriptA.batDo FooEXIT::ScriptB.batDo barEXIT

我删除了所有11个脚本EXIT行并再次尝试,所有11个都在同一命令窗口中按顺序一次运行。

:: OneScriptToRunThemAll.batCALL ScriptA.batCALL ScriptB.batEXIT
::ScriptA.batDo Foo
::ScriptB.batDo bar

如果您想一次打开多个批处理文件,您可以使用call命令。但是,call命令会关闭当前的bat文件并转到另一个文件。如果您想一次打开多个,您可能想尝试以下操作:

@echo offstart cmd "call ex1.bat&ex2.bat&ex3.bat"

依此类推或重复启动cmdcall…”,无论多少文件。这适用于Windows7,但我不确定其他系统。

如果我们有两个批处理脚本,aaa.bat和bbb.bat,并像下面这样调用

call aaa.batcall bbb.bat

执行脚本时,它会先调用aaa.bat,等待线程aaa.bat终止,然后调用bbb.bat.

但是,如果您不想等待aaa.bat终止来调用bbb.bat,请尝试使用开始命令:

START ["title"] [/D path] [/I] [/MIN] [/MAX] [/SEPARATE | /SHARED][/LOW | /NORMAL | /HIGH | /REALTIME | /ABOVENORMAL | /BELOWNORMAL][/AFFINITY <hex affinity>] [/WAIT] [/B] [command/program][parameters]

考试:

start /b aaa.batstart /b bbb.bat
Start msbuild.batStart unit-tests.batStart deploy.bat

如果这不起作用,请将start替换为call或尝试以下操作:

Start msbuild.batGoto :1:1Start unit-tests.batGoto :2:2Start deploy.bat

只需使用call命令!这是一个示例:

call msbuild.batcall unit-tests.batcall deploy.bat

正确的引用(这有时可能很棘手):

start "" /D "C:\Program Files\ProgramToLaunch" "cmd.exe" "/c call ""C:\Program Files\ProgramToLaunch\programname.bat"""

第一个参数-标题(在这种情况下为空)
第二个参数- /D指定起始目录,如果想要当前工作目录,可以省略(例如“%~dp0”)
第3个arg-启动命令,“cmd.exe”
第四个arg-命令的参数,其中参数的引号加倍(这就是您如何在批处理中转义引号中的引号)

并行运行多个批处理文件的最简单方法

start "systemLogCollector" /min cmd /k call systemLogCollector.batstart "uiLogCollector" /min cmd /k call uiLogCollector.batstart "appLogCollector" /min cmd /k call appLogCollector.bat

运行多批处理文件这里有三个批处理文件以最小化的状态在单独的命令窗口上运行。如果您不希望它们最小化,请删除/min。此外,如果您以后不需要控制它们,那么您可以摆脱标题。所以,裸骨命令将是-start cmd /k call systemLogCollector.bat


如果你想终止他们,然后运行这些命令-

taskkill /FI "WindowTitle eq appLogCollector*" /T /Ftaskkill /FI "WindowTitle eq uiLogCollector*" /T /Ftaskkill /FI "WindowTitle eq systemLogCollector*" /T /F

我知道我参加聚会有点晚了,但是还有另一种方法,那就是,这个方法应该等到第一个完成,第二个完成,依此类推。

start "" /wait cmd.exe /c msbuild.batstart "" /wait cmd.exe /c unit-tests.batstart "" /wait cmd.exe /c deploy.bat

使用这种方法可能产生的唯一问题是,随着cmd.exe的新实例的产生,错误级别检查保留在cmd.exe.的每个实例中

或者…

start "" /wait call msbuild.batstart "" /wait call unit-tests.batstart "" /wait call deploy.bat

希望这有帮助。

使用“<强>&

正如你所注意到的,在没有CALL的情况下直接执行bat,STARTCMD /C会导致输入并执行第一个文件,然后在第一个文件完成时进程停止。尽管你仍然可以使用&,这与直接在控制台中使用command1 & command2相同:

(first.bat)&(second.bat)& (third.bat)&(echo other commands)

就机器资源而言,这将是最有效的方式,尽管在最后一个块中,您将无法使用命令行GOTOSHIFTSETLOCAL…并且其功能几乎与在命令提示符中执行命令相同。并且您将无法在最后一个结束括号之后执行其他命令

使用调用

call first.batcall second.batcall third.bat

在大多数情况下,这将是最好的方法-它不创建一个单独的进程,但具有与调用:label作为子例程几乎相同的行为。在MS术语中,它创建一个新的“批处理文件上下文并将控制权传递给指定标签后的语句。第一次遇到批处理文件的结尾(即跳转到标签后)时,控制返回到调用语句后的语句。”

您可以使用在调用文件中设置的变量(如果它们没有在SETLOCAL块中设置),您可以直接访问被调用文件中的标签

CMD /C,管道,FOR /F

其他native选项是使用CMD /C( /C开关将强制调用控制台退出并返回控件)cmd.exe以不透明的方式使用FOR /F对bat文件或使用管道时所做的事情。这将产生一个子进程,该子进程将拥有调用蝙蝠的所有环境。在资源方面效率较低,但由于进程是独立的,解析崩溃或调用EXIT命令不会停止调用. bat

@echo offCMD /c first.batCMD /C second.bat
::not so different than the above lines.:: MORE,FINDSTR,FIND command will be able to read the piped data:: passed from the left side
break|third.bat

START

允许您更灵活地在单独的窗口中启动脚本,无需等待它们完成,设置标题等。默认情况下,它使用CMD /K启动.bat.cmd脚本,这意味着生成的脚本不会自动关闭。再次将所有环境传递给已启动的脚本,并且消耗比cmd /c更多的资源:

:: will be executed in the same console window and will wait to finishstart "" /b /w cmd /c first.bat
::will start in a separate console window and WONT wait to be finished:: the second console window wont close automatically so second.bat might need explicit exit commandstart "" second.bat
::Will start it in a separate window ,but will wait to finish:: closing the second window will cause Y/N prompt:: in the original windowstart "" /w third.cmd

::will start it in the same console window:: but wont wait to finish. May lead to a little bit confusing outputstart "" /b cmd /c fourth.bat

WMIC

与现在的其他方法不同,示例将使用CMD.exe实用程序的外部(默认情况下在Windows上仍然可用)。WMIC实用程序将创建完全独立的进程,因此您无法直接等待完成。虽然WMIC的最佳功能是它返回生成进程的ID:

:: will create a separate process with cmd.exe /cWMIC process call create "%cd%\first.bat","%cd%"
::you can get the PID and monitoring it with other toolsfor /f "tokens=2 delims=;= " %%# in ('WMIC process call create "%cd%\second.bat"^,"%cd%" ^|find "ProcessId"') do (set "PID=%%#")echo %PID%

您还可以使用它在远程机器上启动进程,使用不同的用户等等。

SCHTASKS

使用SCHTASKS提供了一些功能,如(明显的)调度、作为另一个用户(甚至是系统用户)运行、远程机器启动等。再次在完全独立的环境(即它自己的变量)中启动它,甚至是一个隐藏的进程、带有命令参数的xml文件等:

SCHTASKS /create /tn BatRunner /tr "%cd%\first.bat" /sc ONCE /sd 01/01/1910 /st 00:00SCHTASKS /Run /TN BatRunnerSCHTASKS /Delete /TN BatRunner /F

这里也可以从事件日志中获取PID。

ScriptRunner

在启动脚本之间提供一些超时。基本事务功能(即错误回滚)和参数可以放在单独的XML文件中。

::if the script is not finished after 15 seconds (i.e. ends with pause) it will be killedScriptRunner.exe -appvscript %cd%\first.bat -appvscriptrunnerparameters -wait -timeout=15

::will wait or the first called script before to start the second:: if any of the scripts exit with errorcode different than 0 will try:: try to restore the system in the original stateScriptRunner.exe -appvscript second.cmd arg1 arg2 -appvscriptrunnerparameters -wait -rollbackonerror -appvscript third.bat -appvscriptrunnerparameters -wait -timeout=30 -rollbackonerror

您的脚本应该是:

start "msbuild.bat"start "unit-tests.bat"start "deploy.bat"