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

时间:2009-07-09 13:47:14

标签: batch-file cmd

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

commit-build.bat的内容:

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

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

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

20 个答案:

答案 0 :(得分:1061)

使用:

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

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

答案 1 :(得分:164)

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

 call "msbuild.bat"

<强>记录

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

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

在早期,许多批处理文件取决于调用批处理文件不会返回到调用批处理文件的事实。在没有附加语法的情况下更改该行为会破坏许多系统,如批处理菜单系统(使用菜单结构的批处理文件)。

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

<强>提示

如果批处理文件的名称中包含空格,请使用名称旁边的引号:

call "unit tests.bat"

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

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及更高级别。

要控制批处理文件的流程,请转到: - (

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

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

答案 2 :(得分:101)

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

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.

答案 3 :(得分:40)

尝试:

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

答案 4 :(得分:26)

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

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

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

答案 5 :(得分:21)

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

答案 6 :(得分:19)

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

call foo.bat

(是的,这很愚蠢,如果您可以使用foo.bat调用它会更有意义,就像您可以从命令提示符那样调用它,但正确的方法是使用call。)< / p>

答案 7 :(得分:17)

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

call aaa.bat
call bbb.bat

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

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

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.bat
start /b bbb.bat

答案 8 :(得分:7)

查看文件名,您是否考虑过使用NAnt或Ant(Java版本)等构建工具。你将获得比蝙蝠文件更多的控制权。

答案 9 :(得分:5)

Start msbuild.bat
Start unit-tests.bat
Start deploy.bat

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

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

答案 10 :(得分:4)

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

@echo off
start cmd "call ex1.bat&ex2.bat&ex3.bat"

依此类推或重复开始cmdcall ...”,无论多少文件。这适用于 Windows 7 ,但我不确定其他系统。

答案 11 :(得分:2)

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

:: OneScriptToRunThemAll.bat
CALL ScriptA.bat
CALL ScriptB.bat
EXIT

:: ScriptA.bat
Do Foo
EXIT
::ScriptB.bat
Do bar
EXIT

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

:: OneScriptToRunThemAll.bat
CALL ScriptA.bat
CALL ScriptB.bat
EXIT

::ScriptA.bat
Do Foo

::ScriptB.bat
Do bar

答案 12 :(得分:2)

并行运行多个批处理文件

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

running-multiple-batch-files 这三个批处理文件在最小化状态下在单独的命令窗口上运行。如果您不希望它们最小化,请删除/min。另外,如果您以后不需要控制它们,则可以摆脱标题。因此,准系统命令将为-start cmd /k call systemLogCollector.bat


如果要终止它们-

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

答案 13 :(得分:2)

使用“

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

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

从机器资源的角度来看,这是最有效的方法,尽管在最后一块您希望能够使用命令行GOTOSHIFTSETLOCAL ..及其功能几乎与在命令提示符下执行命令相同。最后一个右括号之后,您将无法执行其他命令

Using 呼叫

call first.bat
call second.bat
call third.bat

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

您可以使用在调用文件中设置的变量(如果未在SETLOCAL块中设置变量),可以access directly labels in the called file

CMD /C,管道,FOR /F

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

@echo off
CMD /c first.bat
CMD /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

通过在单独的窗口中启动脚本,不等待其完成,设置标题等功能,使您具有更大的灵活性。默认情况下,它使用.bat启动.cmdCMD /K脚本,这意味着生成的脚本不会自动关闭。再次将所有环境传递给已启动的脚本,并且比{{ 1}}:

cmd /c

WMIC

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

:: will be executed in the same console window and will wait to finish
start "" /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 command
start "" 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 window 
start "" /w third.cmd


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

您还可以使用它在远程计算机上以其他用户身份启动进程,等等。

SCHTASKS

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

:: will create a separate process with cmd.exe /c
WMIC process call create "%cd%\first.bat","%cd%"

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

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

ScriptRunner

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

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

答案 14 :(得分:1)

只需使用val (even, odd) = List(1,2,3,4,5) partition (_ % 2 == 0) 命令即可​​!这是一个例子:

call

答案 15 :(得分:1)

使用正确的引号(有时可能会很棘手):

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

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

答案 16 :(得分:1)

我知道我参加聚会有点晚了,但这是另一种方式。也就是说,此方法应等到第一个完成后再进行第二个,依此类推。

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

使用此方法可能出现的唯一问题是,在生成cmd.exe的新实例的情况下,每个cmd.exe实例中都保留了错误级别检查。

或..

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

希望这会有所帮助。

答案 17 :(得分:1)

你的脚本应该是:

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

答案 18 :(得分:0)

这是我的方式=

cmd /c ""Path_Bat_Here.bat" %ARG%"
:: Or =
Call *.bat

Help = cmd /?

答案 19 :(得分:0)

以下解决了我的问题:

start call "batch1.bat"
start call "batch2.bat"