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

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

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

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

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

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

19 ответов

Решение

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

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

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

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

 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
...

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

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

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.

Пытаться:

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

используя "&"

Как вы заметили, запуск биты напрямую без CALL,START, CMD /Cвызывает ввод и выполнение первого файла, а затем процесс останавливается по завершении первого файла. Хотя вы все еще можете использовать & что будет таким же, как при использовании command1 & command2 прямо в консоли:

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

С точки зрения машинных ресурсов это будет наиболее эффективным способом, хотя в последнем блоке вы хотите иметь возможность использовать командную строку. GOTO,SHIFT,SETLOCAL.. и его возможности будут почти такими же, как при выполнении команд в командной строке. И вы не сможете выполнить другую команду после последней закрывающей скобки

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

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

В большинстве случаев это будет лучший подход - он не создает отдельный процесс, но ведет себя почти так же, как вызов :labelкак подпрограмма. В терминологии MS он создает новый контекст командного файла и передает управление оператору после указанной метки. При первом обнаружении конца командного файла (то есть после перехода к метке) управление возвращается оператору после заявление о вызове ".

Вы можете использовать переменные, установленные в вызываемых файлах (если они не установлены в SETLOCALblock), вы можете напрямую обращаться к меткам в вызываемом файле.

CMD /C, Трубы,FOR /F

разное native вариант - использовать CMD /C (переключатель /C заставит вызываемую консоль выйти и вернуть управление) Что-то, что cmd.exe делает непрозрачным способом с использованием FOR /Fпротив файла bat или когда используются трубы. Это порождает дочерний процесс, в котором будет вся среда вызывающей летучей мыши. Менее эффективен с точки зрения ресурсов, но поскольку процесс отдельный, при анализе происходит сбой или вызывается 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

НАЧАЛО

Обеспечивает большую гибкость, так как возможность запускать сценарии в отдельном окне, не ждать их завершения, устанавливать заголовок и так далее. По умолчанию запускается .bat и .cmd сценарии с CMD /K Это означает, что порожденные скрипты не будут закрыты автоматически. Снова передает всю среду запущенным скриптам и потребляет больше ресурсов, чем cmd /c:

:: 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

WMIC

В отличие от других методов, теперь в примерах будут использоваться внешние служебные программы CMD.exe (которые по-прежнему доступны в Windows по умолчанию). Утилита WMIC создаст полностью отдельный процесс, поэтому вы не сможете напрямую ждать его завершения. Хотя лучшая особенность WMIC заключается в том, что он возвращает идентификатор порожденного процесса:

:: 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%

Вы также можете использовать его для запуска процесса на удаленной машине с другим пользователем и так далее.

SCHTASKS

Использование SCHTASKS предоставляет некоторые функции, такие как (очевидное) планирование, запуск от имени другого пользователя (даже системного пользователя), удаленный запуск машины и так далее. Снова запускает его в совершенно отдельной среде (то есть в собственных переменных) и даже в скрытом процессе, 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

Здесь PID также можно получить из журнала событий.

ScriptRunner

Предлагает некоторый тайм-аут между запускаемыми скриптами. Основные возможности транзакции (например, откат при ошибке) и параметры могут быть помещены в отдельный файл XML.

::if the script is not finished after 15 seconds (i.e. ends with pause) it will be killed
ScriptRunner.exe -appvscript %cd%\first.bat -appvscriptrunnerparameters -wait -timeout=15


::will wait or the first called script before to start the second
:: if any of the scripts exit with errorcode different than 0 will try
:: try to restore the system in the original state
ScriptRunner.exe -appvscript second.cmd arg1 arg2 -appvscriptrunnerparameters -wait -rollbackonerror -appvscript third.bat -appvscriptrunnerparameters -wait -timeout=30 -rollbackonerror

Если у нас есть два пакетных сценария, 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

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

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

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

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

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

call foo.bat

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

Параллельный запуск нескольких пакетных файлов

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
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

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

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

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

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

Ваш сценарий должен быть:

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

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

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

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

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

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

Я знаю, что немного опаздываю на вечеринку, но есть другой выход. То есть этот метод должен дождаться завершения первого, второго и т. Д.

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

Надеюсь это поможет.

Запуск нескольких сценариев в одном у меня была та же проблема. Я продолжал заставлять его умирать на первом, не понимая, что это выход на первом сценарии.

:: 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

Вот мой путь =

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

Помощь = cmd /?

Другие вопросы по тегам