Как запустить несколько файлов .BAT в файле .BAT

696

Я пытаюсь заставить мои commit-build.batвыполнять другие файлы .BAT как часть нашего процесса сборки.

Содержание commit-build.bat:

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

Это кажется достаточно простым, но commit-build.batвыполняет только первый элемент в списке ( msbuild.bat).

Я запустил каждый из файлов отдельно без проблем.

Yvette
источник
4
@sean - Вам не нужно устанавливать полный пакет Cygwin, чтобы заставить работать утилиты командной строки. Просто выньте все библиотеки cygwin из пакета, поместите их в каталог с патчами, поместите все свои инструменты в другой каталог с патчами, и все готово.
Технарь Джо
при условии, что каждый из этих файлов является только пакетным, почему бы просто не поместить их в один большой файл и использовать функцию тайм-аута, чтобы каждый раз запускаться.
CMS_95

Ответы:

1202

Использование:

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

Если CALL не используется, текущий пакетный файл останавливается, и запускаемый вызываемый пакетный файл начинает выполняться. Это своеобразное поведение, восходящее к ранним дням MS-DOS.

Филипп Лейбер
источник
странно, я пробовал без «вызова» на Windows 7, и я помню, что он работал, но на Windows XP это требовало этой команды. это может быть?
Android-разработчик
7
Без вызова, в соответствии с оригинальной спецификацией DOS, следует выполнить цепочку команд и НЕ возвращать. Еще до того, как был добавлен «CALL», популярной опцией было открывать дочернюю командную строку, например «command / c second.bat», поскольку она также будет возвращаться.
Брайан Кноблаух
1
У меня была проблема с Windows 7, так что это не только XP
Рафики
7
В Windows 10 выполняется только первая строка. Ответ, однако, сработал.
Робро
2
Как передать параметры в пакетные файлы, и одним из параметров является путь с пробелами.
Зевс
180

Все остальные ответы верны: используйте звонок. Например:

 call "msbuild.bat"

история

В древних версиях DOS было невозможно рекурсивно выполнять командные файлы. Затем была введена команда call, которая вызывала другую командную оболочку cmd для выполнения командного файла и вернула выполнение обратно в вызывающую командную оболочку, когда закончил.

Очевидно, что в более поздних версиях больше нет необходимости в другой оболочке cmd.

В первые дни многие пакетные файлы зависели от того, что вызов пакетного файла не вернется к вызывающему пакетному файлу. Изменение этого поведения без дополнительного синтаксиса нарушило бы многие системы, такие как системы пакетного меню (используя пакетные файлы для структур меню).

Как и во многих случаях с 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>

Используйте, if errorlevel 1если у вас Windows более старая, чем NT4 / 2000 / XP, чтобы перехватить все уровни ошибок 1 и выше.

Для управления потоком командного файла есть goto :-(

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

Как отмечали другие: взгляните на системы сборки для замены командных файлов.

Ральф М. Рикенбах
источник
согласился, но цикл мог, в этом случае, обрабатывать файлы в неправильном (алфавитном?) порядке
Дейв Арчер
Хороший и очень полный ответ. Если вы включаете поток управления, было бы хорошо отметить, что вместо goto вы можете выполнять подпрограммы с помощью call: label1, а оператор return в пакетных файлах - это немного странный goto: eof (и не нужно сделайте ярлык eof самостоятельно, который существует по умолчанию).
Леголас
errorlevelпример команды дал мне проблему на Windows 10 (в CMD консоли). Я изменил команду просто так if errorlevel neq echo Houston We have a Problem!. Мой пакетный процесс не имел проблем и завершался в основном нормально, но на каждом этапе использования этой команды после оператора call я получал «neq был неожиданным в это время». Думая, что они могли изменить неравный синтаксис, я попытался, но !=также <>продолжал получать ту же ошибку «в этот раз не ожидалось» для нового синтаксиса. что я могу делать не так?
TMWP
118

Если мы хотим открыть несколько командных строк, то мы могли бы использовать

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.
Фарин
источник
7
это то, что мы искали, так как наше первое приложение блокирует консоль, спасибо за подсказку
Майкл Мёллер
1
это будет запускать несколько экземпляров команды и даже работать для запуска нескольких пакетных файлов с <pause>. +1, так как это именно то решение, которое я искал!
Кристиан Ноэль
5
не могли бы вы объяснить, что эти цифры в вашем ответе? Их цель не ясна.
Каламалка Малыш
3
Обратите внимание, что большинство людей, вероятно, хотят использовать start "Window title" /wait cmd /k call something.batдля того, чтобы запустить вещи в последовательном порядке.
Андрей
3
(или start "Window title" /wait cmd /c something.bat, где cmd /cзакрывается окно, когда закончил)
Андрей
42

Пытаться:

call msbuild.bat
call unit-tests.bat
call deploy.bat
Джонатан
источник
28

Вы вызываете несколько пакетов, чтобы скомпилировать программу. Я считаю само собой разумеющимся, что в случае возникновения ошибки:
1) программа в пакете завершит работу с уровнем ошибки;
2) Вы хотите знать об этом.

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

'||' проверяет уровень ошибки выше 0. Таким образом, все пакеты вызываются по порядку, но останавливаются при любой ошибке, оставляя экран, в котором вы видите любое сообщение об ошибке.

сойка
источник
23

Если у нас есть два пакетных сценария, 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
user2314621
источник
22
call msbuild.bat
call unit-tests.bat
call deploy.bat
butterchicken
источник
20

Чтобы вызвать .batфайл в .batфайле, используйте

call foo.bat

(Да, это глупо, было бы больше смысла, если бы вы могли вызывать его foo.bat, как вы могли бы из командной строки, но правильный способ - использовать call.)

Zifre
источник
7

Глядя на ваши имена файлов, вы рассматривали возможность использования инструмента сборки, такого как NAnt или Ant (версия Java). Вы получите намного больший контроль, чем с файлами bat.

Дейв Арчер
источник
7

Если вы хотите открыть много командных файлов одновременно, вы можете использовать команду call. Однако команда call закрывает текущий файл bat и переходит к другому. Если вы хотите открыть много сразу, вы можете попробовать это:

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

И так далее или повторите запуск cmd" call..." для любого количества файлов. Это работает для Windows 7 , но я не уверен насчет других систем.

CMS_95
источник
6
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
McOussKing
источник
3

Просто используйте callкоманду! Вот пример:

call msbuild.bat
call unit-tests.bat
call deploy.bat
PryroTech
источник
3

При правильном цитировании (иногда это бывает сложно):

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

1-й аргумент - заголовок (в данном случае пуст)
2-й аргумент - / D указывает начальный каталог, может быть пропущен, если требуется текущий рабочий каталог (например, «% ~ dp0»)
3-й аргумент - команда для запуска, «cmd.exe»
4-й arg - аргументы для команды, с двойными кавычками для аргументов внутри (это то, как вы избегаете кавычек в кавычках в пакете)

robertcollier4
источник
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
Джон Олифант
источник
не удаляйте exits, замените их goto :eofвместо этого. Это «возвращение» кcall
Stephan
вы понимаете, что в простых пакетных командах будут запускаться в порядке их вызова, а также базовый макет для индексов, @echo off :menu some commands goto menuобратите внимание, что это будет выполнять непрерывный цикл до закрытия. в основном вам не нужно ::просто:
CMS_95
0

Следующее решило мою проблему:

start call "batch1.bat"
start call "batch2.bat"
Quinn
источник
0

Может быть, вы хотите это:

Запустите пакетные сценарии параллельно

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

Здесь три пакетных файла запускаются в отдельных командных окнах в свернутом состоянии. Если вы не хотите минимизировать их, удалите /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
Минхас Камаль
источник