Cómo ejecutar múltiples archivos .BAT dentro de un archivo .BAT

694

Estoy tratando de commit-build.batejecutar otros archivos .BAT como parte de nuestro proceso de compilación.

Contenido de commit-build.bat:

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

Esto parece bastante simple, pero commit-build.batsolo ejecuta el primer elemento de la lista ( msbuild.bat).

He ejecutado cada uno de los archivos por separado sin problemas.

Yvette
fuente
44
@sean: no tiene que instalar el paquete completo de Cygwin para que las utilidades de la línea de comandos funcionen. Simplemente saque todos los dlls de cygwin del paquete, colóquelos en un directorio con parches, coloque todas sus herramientas en otro directorio con parches y listo.
Techie Joe
presumiendo que cada uno de estos archivos es solo un lote, ¿por qué no solo ponerlos en un archivo grande y usar la función de tiempo de espera para permitir que cada vez comience?
CMS_95

Respuestas:

1199

Utilizar:

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

Cuando no usa CALL, el archivo por lotes actual se detiene y el archivo por lotes llamado comienza a ejecutarse. Es un comportamiento peculiar que se remonta a los primeros días de MS-DOS.

Philippe Leybaert
fuente
raro, he intentado sin la "llamada" en Windows 7 y recuerdo que funcionó, pero en Windows XP requería este comando. ¿podría ser?
desarrollador de Android
77
Sin llamada, según la especificación original de DOS, debe hacer el encadenamiento de comandos y NO regresar. Una opción popular antes de agregar "CALL" era abrir un símbolo del sistema secundario como "command / c second.bat", ya que eso también volverá.
Brian Knoblauch
1
Tuve el problema en Windows 7 entreprise, así que no solo es xp
Rafiki
55
En Windows 10 solo se ejecuta la primera línea. Sin embargo, la respuesta de farheen funcionó.
robro
2
Cómo pasar parámetros a los archivos por lotes, y uno de los parámetros es una ruta con espacios.
Zeus
179

Todas las otras respuestas son correctas: use call. Por ejemplo:

 call "msbuild.bat"

Historia

En versiones antiguas de DOS no era posible ejecutar recursivamente archivos por lotes. Luego, se introdujo el comando de llamada que llamó a otro cmd shell para ejecutar el archivo por lotes y devolvió la ejecución al cmd shell de llamada cuando finalizó.

Obviamente, en versiones posteriores ya no era necesario ningún otro cmd shell.

En los primeros días, muchos archivos por lotes dependían del hecho de que llamar a un archivo por lotes no volvería al archivo por lotes de llamada. Cambiar ese comportamiento sin una sintaxis adicional habría roto muchos sistemas, como los sistemas de menú por lotes (usando archivos por lotes para estructuras de menú).

Como en muchos casos con Microsoft, la compatibilidad con versiones anteriores es la razón de este comportamiento.

Consejos

Si sus archivos por lotes tienen espacios en sus nombres, use comillas alrededor del nombre:

call "unit tests.bat"

Por cierto: si no tiene todos los nombres de los archivos por lotes, también puede usar para hacer esto (no garantiza el orden correcto de las llamadas de archivos por lotes; sigue el orden del sistema de archivos):

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

También puede reaccionar ante niveles de error después de una llamada. Utilizar:

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

devolver un nivel de error. 0 denota la ejecución correcta. En el archivo por lotes de llamada puede reaccionar usando

if errorlevel neq 0 <batch command>

Úselo if errorlevel 1si tiene un Windows anterior a NT4 / 2000 / XP para capturar todos los niveles de error 1 y superiores.

Para controlar el flujo de un archivo por lotes, hay goto :-(

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

Como otros señalaron: eche un vistazo a los sistemas de compilación para reemplazar los archivos por lotes.

Ralph M. Rickenbach
fuente
estuvo de acuerdo, pero el bucle podría, en este caso, procesar los archivos en el orden incorrecto (¿alfabético?)
Dave Archer
Bonita y muy completa respuesta. Si incluye el flujo de control, puede ser bueno tener en cuenta que en lugar de ir a goto, puede hacer subrutinas usando call: label1, y la declaración 'return' en los archivos por lotes es un poco extraño goto: eof (y no es necesario) haga usted mismo una etiqueta eof, que existe por defecto).
Legolas
El errorlevelejemplo de comando me dio un problema en Windows 10 (en la consola cmd). Modifiqué el comando simplemente para ser if errorlevel neq echo Houston We have a Problem!. Mi proceso por lotes no tuvo problemas y se completó en su mayoría normalmente, pero en cada paso del camino donde usé este comando después de una declaración de llamada, recibí "neq fue inesperado en este momento". Pensando que pueden haber cambiado la sintaxis no igual, lo intenté !=y también, <>pero seguí obteniendo el mismo error "no esperado en este momento" para la nueva sintaxis. ¿Qué podría estar haciendo mal?
TMWP
117

Si deseamos abrir múltiples solicitudes de comando, entonces podríamos usar

start cmd /k

/k: es obligatorio lo que se ejecutará.

El lanzamiento de muchas indicaciones de comando se puede hacer de la siguiente manera.

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
fuente
77
eso es lo que estábamos buscando, ya que nuestra primera aplicación bloquea la consola, gracias por la pista
Michael Moeller
1
esto ejecutará múltiples instancias de comando e incluso funcionará para ejecutar múltiples archivos por lotes que tienen <pausa>. ¡+1 ya que esta es exactamente la solución que estaba buscando!
Christian Noel
55
¿podría explicar que esos números están en su respuesta? Su propósito no está claro.
Kalamalka Kid
3
Tenga en cuenta que la mayoría de la gente probablemente quiera usar start "Window title" /wait cmd /k call something.batpara ejecutar cosas en orden secuencial.
Andrew
3
(o start "Window title" /wait cmd /c something.bat, donde cmd /ccierra la ventana una vez terminado)
Andrew
42

Tratar:

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

Estás llamando a varios lotes en un esfuerzo por compilar un programa. Doy por sentado que si ocurre un error:
1) El programa dentro del lote saldrá con un nivel de error;
2) Quieres saber al respecto.

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

'||' prueba un nivel de error superior a 0. De esta forma, todos los lotes se llaman en orden, pero se detendrán ante cualquier error, dejando la pantalla como está para que pueda ver cualquier mensaje de error.

Arrendajo
fuente
23

Si tenemos dos scripts por lotes, aaa.bat y bbb.bat, y llama como a continuación

call aaa.bat
call bbb.bat

Al ejecutar el script, primero llamará a aaa.bat, esperará a que termine el hilo de aaa.bat y llamará a bbb.bat.

Pero si no desea esperar a que aaa.bat termine para llamar a bbb.bat, intente usar el 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]

Examen:

start /b aaa.bat
start /b bbb.bat
usuario2314621
fuente
22
call msbuild.bat
call unit-tests.bat
call deploy.bat
pollo de mantequilla
fuente
20

Para llamar a un .batarchivo dentro de un .batarchivo, use

call foo.bat

(Sí, esto es una tontería, tendría más sentido si pudiera llamarlo foo.bat, como podría hacerlo desde el símbolo del sistema, pero la forma correcta es usarlo call).

Zifre
fuente
7

Mirando sus nombres de archivos, ¿ha considerado usar una herramienta de compilación como NAnt o Ant (la versión Java). Obtendrá mucho más control que con los archivos bat.

Dave Archer
fuente
7

Si desea abrir muchos archivos por lotes a la vez, puede usar el comando de llamada. Sin embargo, el comando de llamada cierra el archivo bat actual y pasa a otro. Si desea abrir muchos a la vez, puede probar esto:

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

Y así sucesivamente o repita el inicio cmd" call..." para la cantidad de archivos. Esto funciona para Windows 7 , pero no estoy seguro de otros sistemas.

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

Si eso no funciona, reemplace startcon callo intente lo siguiente:

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

¡Solo usa el callcomando! Aquí hay un ejemplo:

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

Con una cita correcta (esto puede ser complicado a veces):

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

1er arg - Título (vacío en este caso)
2do arg - / D especifica el directorio de inicio, se puede omitir si se desea el directorio de trabajo actual (como "% ~ dp0")
3er arg - comando para iniciar, "cmd.exe"
4to arg: argumentos para ordenar, con comillas duplicadas para los argumentos que contiene (así es como se escapan las comillas dentro de comillas en lote)

robertcollier4
fuente
2

Al ejecutar varios scripts en uno, tuve el mismo problema. Seguí haciéndolo morir en el primero sin darme cuenta de que estaba saliendo en el primer guión.

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

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

Eliminé las 11 líneas de EXIT de mis scripts e intenté nuevamente y las 11 se ejecutaron en orden una a la vez en la misma ventana de comandos.

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

::ScriptA.bat
Do Foo

::ScriptB.bat
Do bar
John Oliphant
fuente
no elimine los exits, reemplácelos por ellos goto :eof. Esto "volverá" alcall
Stephan
se da cuenta de que, en un lote simple, los comandos se ejecutarán en el orden en que se llaman, también el diseño básico para los índices, @echo off :menu some commands goto menutenga en cuenta que esto ejecutará un ciclo continuo hasta que se cierre. básicamente no necesitas el ::justo:
CMS_95
0

Lo siguiente resolvió mi problema:

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

Puede ser que quieras esto:

Ejecute las secuencias de comandos por lotes en 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

Aquí se ejecutan tres archivos por lotes en ventanas de comandos separadas en estado minimizado. Si no quiere que se minimicen, elimínelos /min. Además, si no necesita controlarlos más tarde, puede deshacerse de los títulos. Entonces, un comando básico será-start cmd /k call systemLogCollector.bat


Si quieres terminarlos-

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