Como executar vários arquivos .BAT em um arquivo .BAT

694

Estou tentando fazer com que meus commit-build.batoutros arquivos .BAT sejam executados como parte do nosso processo de compilação.

Conteúdo de commit-build.bat:

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

Isso parece bastante simples, mas commit-build.batapenas executa o primeiro item da lista ( msbuild.bat).

Eu executei cada um dos arquivos separadamente, sem problemas.

Yvette
fonte
4
@sean - Você não precisa instalar o pacote completo do Cygwin para que os utilitários da linha de comando funcionem. Apenas retire todas as dlls cygwin do pacote, coloque-as em um diretório de caminho, coloque todas as suas ferramentas em outro diretório de caminho e você estará pronto.
9133 Techie Joe
presumindo que cada um desses arquivos seja apenas em lote, por que não apenas colocá-los em um arquivo grande e usar a função de tempo limite para permitir o início de cada vez.
CMS_95

Respostas:

1199

Usar:

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

Quando não estiver usando CALL, o arquivo em lotes atual será interrompido e o arquivo em lote chamado começará a ser executado. É um comportamento peculiar que remonta aos primeiros dias do MS-DOS.

Philippe Leybaert
fonte
estranho, eu tentei sem a "chamada" no Windows 7 e lembro que funcionou, mas no Windows XP exigiu este comando. poderia ser?
desenvolvedor android
7
Sem chamada, de acordo com a especificação original do DOS, deve fazer o encadeamento de comandos e NÃO retornar. Uma opção popular anterior à adição de "CALL" era abrir um prompt de comando filho como "command / c second.bat", pois isso também retornará.
Brian Knoblauch
1
Eu tive o problema no Windows 7 entreprise por isso não é única xp
Rafiki
5
No Windows 10, apenas a primeira linha é executada. A resposta dos farheen, no entanto, funcionou.
Robro
2
Como passar parâmetros para os arquivos em lotes, e um dos parâmetros é um caminho com espaços.
Zeus
179

Todas as outras respostas estão corretas: use call. Por exemplo:

 call "msbuild.bat"

História

Nas versões antigas do DOS, não era possível executar recursivamente arquivos em lote. Em seguida, foi introduzido o comando de chamada que chamou outro shell do cmd para executar o arquivo em lotes e retornou a execução de volta ao shell do cmd quando terminar.

Obviamente, em versões posteriores, nenhum outro shell cmd era mais necessário.

Nos primeiros dias, muitos arquivos em lotes dependiam do fato de que a chamada de um arquivo em lotes não retornaria ao arquivo em lotes de chamada. Alterar esse comportamento sem sintaxe adicional teria quebrado muitos sistemas, como sistemas de menus em lotes (usando arquivos em lotes para estruturas de menus).

Como em muitos casos com a Microsoft, a compatibilidade com versões anteriores, portanto, é a razão desse comportamento.

Dicas

Se seus arquivos em lotes tiverem espaços em seus nomes, use aspas ao redor do nome:

call "unit tests.bat"

A propósito: se você não tiver todos os nomes dos arquivos em lote, também poderá usá-lo (isso não garante a ordem correta das chamadas de arquivos em lote; segue a ordem do sistema de arquivos):

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

Você também pode reagir aos níveis de erro após uma chamada. Usar:

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

para retornar um nível de erro. 0 indica execução correta. No arquivo em lotes de chamada, você pode reagir usando

if errorlevel neq 0 <batch command>

Use if errorlevel 1se você tiver um Windows mais antigo que o NT4 / 2000 / XP para capturar todos os níveis de erro 1 e superior.

Para controlar o fluxo de um arquivo em lotes, existe o seguinte :-(

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

Como outros apontaram: dê uma olhada nos sistemas de compilação para substituir arquivos em lote.

Ralph M. Rickenbach
fonte
concordou, mas o loop poderia, neste caso, processar os arquivos no errado (? alfabética) ordem
Dave Archer
Resposta agradável e muito completa. Se você estiver incluindo o fluxo de controle, pode ser bom observar que, em vez de ir para goto, você pode executar sub-rotinas usando call: label1, e a instrução 'return' em arquivos em lote é a goto: eof um pouco estranha (e não é necessário faça você mesmo um rótulo Eof, que exista por padrão).
precisa
o errorlevelexemplo de comando me deu um problema no Windows 10 (no console do cmd). Eu modifiquei o comando simplesmente para ser if errorlevel neq echo Houston We have a Problem!. Meu processo em lote não teve problemas e foi concluído normalmente, mas em todas as etapas em que usei esse comando após uma declaração de chamada, obtive "neq era inesperado no momento". Pensando que eles podem ter alterado a sintaxe diferente, tentei !=e também <>continuava recebendo o mesmo erro "não esperado no momento" para a nova sintaxe. o que eu poderia estar fazendo de errado?
TMWP
117

Se queremos abrir vários prompts de comando, podemos usar

start cmd /k

/k: é obrigatório que será executado.

O lançamento de muitos prompts de comando pode ser feito como abaixo.

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.
farheen
fonte
7
era isso que estávamos procurando, pois nosso primeiro aplicativo bloqueia o console, obrigado pela dica
Michael Moeller
1
isso executará várias instâncias de comando e até funcionará para a execução de vários arquivos em lotes com <pausa>. +1, pois esta é exatamente a solução que eu estava procurando!
Christian Noel
5
você poderia explicar que esses números estão na sua resposta? Seu objetivo não é claro.
Kalamalka Kid
3
Observe que a maioria das pessoas provavelmente deseja usar start "Window title" /wait cmd /k call something.batpara executar as coisas em ordem seqüencial.
Andrew
3
(ou start "Window title" /wait cmd /c something.bat, onde cmd /cfecha a janela uma vez terminado)
Andrew
42

Tentar:

call msbuild.bat
call unit-tests.bat
call deploy.bat
Jonathan
fonte
28

Você está chamando vários lotes em um esforço para compilar um programa. Tomo como certo que, se ocorrer um erro:
1) O programa no lote será encerrado com um nível de erro;
2) Você quer saber sobre isso.

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

'||' testa um nível de erro maior que 0. Dessa forma, todos os lotes são chamados em ordem, mas param a qualquer erro, deixando a tela como é para você ver qualquer mensagem de erro.

Jay
fonte
23

Se tivermos dois scripts em lote, aaa.bat e bbb.bat, e chame como abaixo

call aaa.bat
call bbb.bat

Ao executar o script, ele chamará aaa.bat primeiro, espere o encadeamento de aaa.bat terminar e chame bbb.bat.

Mas se você não quiser esperar que o aaa.bat termine para chamar bbb.bat, tente usar o comando START :

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

Exame:

start /b aaa.bat
start /b bbb.bat
user2314621
fonte
22
call msbuild.bat
call unit-tests.bat
call deploy.bat
manteiga
fonte
20

Para chamar um .batarquivo dentro de um .batarquivo, use

call foo.bat

(Sim, isso é bobagem, faria mais sentido se você pudesse chamá-lo com foo.bat, como no prompt de comando, mas a maneira correta é usá-lo call.)

Zifre
fonte
7

Olhando para seus nomes de arquivos, você já pensou em usar uma ferramenta de construção como NAnt ou Ant (a versão Java). Você terá muito mais controle do que com arquivos bat.

Dave Archer
fonte
7

Se você deseja abrir muitos arquivos em lotes de uma só vez, pode usar o comando call. No entanto, o comando call fecha o arquivo bat atual e vai para outro. Se você deseja abrir muitos de uma vez, tente o seguinte:

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

E assim por diante ou repita o início cmd" call..." para muitos arquivos. Isso funciona no Windows 7 , mas não tenho certeza sobre outros sistemas.

CMS_95
fonte
6
Start msbuild.bat
Start unit-tests.bat
Start deploy.bat

Se isso não funcionar, substitua startpor callou tente o seguinte:

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

Basta usar o callcomando! Aqui está um exemplo:

call msbuild.bat
call unit-tests.bat
call deploy.bat
PryroTech
fonte
3

Com a citação correta (às vezes pode ser complicado):

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

1 arg - Título (esvaziar neste caso)
2 arg - / especifica D diretório de partida, pode ser omitido se quer que o dir atual de trabalho (como "% ~ DP0")
3ª arg - comando para lançamento, "cmd.exe"
4 arg - argumentos para comando, com aspas dobradas para os argumentos contidos nele (é assim que você escapa aspas entre aspas em lote)

robertcollier4
fonte
2

Executando vários scripts em um, tive o mesmo problema. Eu continuei morrendo no primeiro, sem perceber que estava saindo no primeiro script.

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

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

Eu removi todas as 11 linhas EXIT dos meus scripts e tentei novamente e todas as 11 foram executadas em ordem uma de cada vez na mesma janela de comando.

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

::ScriptA.bat
Do Foo

::ScriptB.bat
Do bar
John Oliphant
fonte
não remova os exit, substitua-os por goto :eof. Isso "retornará" para ocall
Stephan
você percebe que, em um lote simples, os comandos serão executados na ordem em que também são chamados de layout básico dos índices. @echo off :menu some commands goto menuObserve que isso executará um loop contínuo até ser fechado. basicamente, você não precisa a ::apenas:
CMS_95
0

A seguir, resolvi meu problema:

start call "batch1.bat"
start call "batch2.bat"
Quinn
fonte
0

Pode ser que você queira isso:

Execute os scripts em lote em paralelo

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

Aqui, três arquivos em lote são executados em janelas de comando separadas no estado minimizado. Se você não os quer minimizados, remova-os /min. Além disso, se você não precisar controlá-los mais tarde, poderá se livrar dos títulos. Portanto, um comando básico serástart cmd /k call systemLogCollector.bat


Se você deseja finalizá-los,

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