Come eseguire più file .BAT all'interno di un file .BAT


696

Sto cercando di far commit-build.bateseguire altri file .BAT come parte del nostro processo di compilazione.

Contenuto di commit-build.bat:

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

Sembra abbastanza semplice, ma commit-build.batesegue solo il primo elemento nell'elenco ( msbuild.bat).

Ho eseguito ciascuno dei file separatamente senza problemi.


4
@sean - Non è necessario installare il pacchetto Cygwin completo per far funzionare le utility della riga di comando. Basta estrarre tutte le dll cygwin dal pacchetto e posizionarle in una directory con percorso, mettere tutti gli strumenti in un'altra directory con percorso e il gioco è fatto.
Techie Joe

presumendo che ciascuno di questi file sia solo batch, perché non semplicemente inserirli in un file di grandi dimensioni e utilizzare la funzione di timeout per consentire ogni volta l'avvio.
CMS_95,

Risposte:


1202

Uso:

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

Quando non si utilizza CALL, il file batch corrente si interrompe e inizia l'esecuzione del file batch chiamato. È un comportamento peculiare che risale ai primi giorni di MS-DOS.


strano, ho provato senza la "chiamata" su Windows 7 e ricordo che ha funzionato, ma su Windows XP ha richiesto questo comando. potrebbe essere?
sviluppatore Android

7
Senza chiamata, secondo le specifiche DOS originali, dovrebbe eseguire il concatenamento dei comandi e NON restituire. Un'opzione popolare prima dell'aggiunta di "CALL" era l'apertura di un prompt dei comandi figlio come "command / c second.bat", poiché anche quello tornerà.
Brian Knoblauch,

1
Ho avuto il problema con Windows 7, quindi non è solo XP
Rafiki

7
Su Windows 10 viene eseguita solo la prima riga. La risposta di Farheen tuttavia ha funzionato.
robro

2
Come passare i parametri ai file batch e uno dei parametri è un percorso con spazi.
Zeus

180

Tutte le altre risposte sono corrette: usa la chiamata. Per esempio:

 call "msbuild.bat"

Storia

Nelle antiche versioni DOS non era possibile eseguire in modo ricorsivo file batch. Quindi è stato introdotto il comando call che ha chiamato un'altra shell cmd per eseguire il file batch e al termine ha restituito l'esecuzione alla shell cmd chiamante.

Ovviamente nelle versioni successive non era più necessaria alcuna altra shell cmd.

All'inizio molti file batch dipendevano dal fatto che la chiamata a un file batch non sarebbe tornata al file batch chiamante. La modifica di tale comportamento senza sintassi aggiuntiva avrebbe interrotto molti sistemi come i sistemi di menu batch (utilizzando file batch per strutture di menu).

Come in molti casi con Microsoft, la compatibilità con le versioni precedenti è quindi la ragione di questo comportamento.

Suggerimenti

Se i tuoi file batch hanno spazi nei loro nomi, usa le virgolette attorno al nome:

call "unit tests.bat"

A proposito: se non si hanno tutti i nomi dei file batch, è possibile utilizzare anche per fare ciò (non garantisce l'ordine corretto delle chiamate di file batch; segue l'ordine del file system):

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

Puoi anche reagire a livelli di errore dopo una chiamata. Uso:

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

per restituire un livello di errore. 0 indica la corretta esecuzione. Nel file batch chiamante puoi reagire usando

if errorlevel neq 0 <batch command>

Uso if errorlevel 1 se si dispone di una Windows precedente a NT4 / 2000 / XP per rilevare tutti i livelli di errore 1 e superiori.

Per controllare il flusso di un file batch, c'è goto :-(

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

Come altri hanno sottolineato: dai un'occhiata ai sistemi di build per sostituire i file batch.


d'accordo, ma il loop potrebbe, in questo caso, elaborare i file nell'ordine sbagliato (in ordine alfabetico?)
Dave Archer,

Risposta piacevole e molto completa. Se stai includendo il flusso di controllo, potrebbe essere utile notare che, al posto di goto, puoi fare subroutine usando call: label1, e l'istruzione 'return' nei file batch è leggermente goto: eof (e non c'è bisogno di crea tu stesso un'etichetta eof, che esiste di default).
Legolas,

l' errorlevelesempio di comando mi ha dato un problema su Windows 10 (nella console cmd). Ho modificato il comando semplicemente per essere if errorlevel neq echo Houston We have a Problem!. Il mio processo batch non ha avuto problemi e si è concluso per lo più normalmente, ma in ogni fase del modo in cui ho usato questo comando dopo un'istruzione call, ho ottenuto "neq era inaspettato in questo momento". Pensando che potrebbero aver cambiato la sintassi non uguale, ho provato !=e ho anche <>continuato a ottenere lo stesso errore "non previsto in questo momento" per la nuova sintassi. cosa potrei fare di sbagliato?
TMWP

118

Se vogliamo aprire più prompt dei comandi, allora potremmo usare

start cmd /k

/k: è obbligatorio che verrà eseguito.

L'avvio di molti prompt dei comandi può essere eseguito come di seguito.

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.

7
questo è quello che stavamo cercando, poiché la nostra prima app blocca la console, grazie per il suggerimento
Michael Moeller,

1
questo eseguirà più istanze di comando e funzionerà anche per l'esecuzione di più file batch che hanno <pause>. +1 poiché questa è esattamente la soluzione che stavo cercando!
Christian Noel,

5
potresti per favore spiegare che quei numeri sono nella tua risposta? Il loro scopo non è chiaro.
Kalamalka Kid,

3
Nota che molte persone probabilmente vogliono usarlo start "Window title" /wait cmd /k call something.batper eseguire le cose in ordine sequenziale.
Andrew,

3
(o start "Window title" /wait cmd /c something.bat, dove cmd /cuna volta chiusa la finestra una volta terminata)
Andrew,

42

Provare:

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

28

Stai chiamando più batch nel tentativo di compilare un programma. Dò per scontato che se si verifica un errore:
1) Il programma all'interno del batch verrà chiuso con un livello di errore;
2) Vuoi saperlo.

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

'||' verifica un livello di errore superiore a 0. In questo modo tutti i batch vengono chiamati in ordine ma si fermano a qualsiasi errore, lasciando lo schermo com'è per te vedere qualsiasi messaggio di errore.


23

Se abbiamo due script batch, aaa.bat e bbb.bat, e chiamiamo come di seguito

call aaa.bat
call bbb.bat

Quando esegue lo script, chiamerà prima aaa.bat, attenderà il termine del thread di aaa.bat e chiamerà bbb.bat.

Ma se non vuoi aspettare che aaa.bat termini per chiamare bbb.bat, prova a usare il 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]

Esame:

start /b aaa.bat
start /b bbb.bat


20

Per chiamare un .batfile all'interno di un .batfile, utilizzare

call foo.bat

(Sì, questo è stupido, avrebbe più senso se tu potessi chiamarlo foo.bat, come potresti dal prompt dei comandi, ma il modo corretto è quello di usare call.)


7

Guardando i tuoi nomi di file, hai preso in considerazione l'utilizzo di uno strumento di compilazione come NAnt o Ant (la versione Java). Otterrai un controllo molto maggiore rispetto ai file bat.


7

Se si desidera aprire più file batch contemporaneamente, è possibile utilizzare il comando call. Tuttavia, il comando call chiude il file bat corrente e passa a un altro. Se vuoi aprirne molti contemporaneamente, potresti provare questo:

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

E così via o ripetere l'avvio cmd" call..." per molti file. Funziona con Windows 7 , ma non sono sicuro di altri sistemi.


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

Se questo non funziona, sostituire startcon callo provare questo:

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

3

Usa il callcomando! Ecco un esempio:

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

3

Con una quotazione corretta (a volte può essere difficile):

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

1st arg - Titolo (vuoto in questo caso)
2nd arg - / D specifica la directory iniziale, può essere ommited se si desidera la directory di lavoro corrente (come "% ~ dp0")
3rd arg - comando per avviare, "cmd.exe"
4 ° arg - argomenti da comandare, con virgolette raddoppiate per gli argomenti al suo interno (ecco come sfuggire alle virgolette tra virgolette in batch)


2

Eseguendo più script in uno ho avuto lo stesso problema. Continuavo a farlo morire sul primo senza rendermi conto che stava uscendo con il primo copione.

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

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

Ho rimosso tutte e 11 le righe EXIT dei miei script e riprovato e tutte e 11 sono state eseguite in ordine uno alla volta nella stessa finestra di comando.

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

::ScriptA.bat
Do Foo

::ScriptB.bat
Do bar

non rimuovere le exits, sostituirle goto :eofinvece con . Questo "ritornerà" acall
Stephan il

ti rendi conto che in un semplice batch i comandi verranno eseguiti nell'ordine in cui vengono chiamati anche il layout di base per gli indici @echo off :menu some commands goto menunota che questo eseguirà un ciclo continuo fino alla chiusura. in pratica non hai bisogno del ::giusto:
CMS_95

0

Quanto segue ha risolto il mio problema:

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

0

Forse vuoi questo:

Esegui gli script batch in parallelo-

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

Qui tre file batch vengono eseguiti su finestre di comando separate in stato ridotto. Se non li vuoi minimizzare, rimuovili /min. Inoltre, se non è necessario controllarli in un secondo momento, è possibile eliminare i titoli. Quindi, un comando a osso nudo sarà-start cmd /k call systemLogCollector.bat


Se vuoi terminarli-

taskkill /FI "WindowTitle eq appLogCollector*" /T /F
taskkill /FI "WindowTitle eq uiLogCollector*" /T /F
taskkill /FI "WindowTitle eq systemLogCollector*" /T /F
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.