Skip to main content

How to Chain Multiple Batch Scripts Together Sequentially

Complex automation systems are rarely built as a single, massive file. Instead, they are broken down into modular scripts, one for "Setup," one for "Data Processing," and one for "Cleanup." Chaining these scripts together allows you to build sophisticated workflows while keeping your code organized and easy to debug. However, if you don't use the correct syntax, your master script might "stop" after the first child script completes, leaving the rest of your process unfinished.

This guide will explain how to use the CALL command and logical operators to chain Batch scripts together correctly.

The "Call" Requirement

In Windows Batch, if you simply type the name of another script, the current script "transfers" control to the new one and never comes back. To run a script and then return to the parent to continue the next task, you must use the CALL command.

Wrong Way (Chaining ends at Script1):

@echo off
script1.bat
script2.bat
echo This will never be printed.

Correct Way (Full Sequential Chain):

@echo off
echo Starting Master Process...

call script1.bat
call script2.bat
echo All tasks finished.

Method 1: The Master Controller Pattern

This is the standard approach for managing a multi-stage project. Each stage is verified before proceeding to the next.

@echo off
setlocal

title Pipeline Manager
set "ScriptDir=%~dp0scripts"
set "LogFile=%~dp0pipeline.log"

echo [PIPELINE] Starting at %date% %time%
echo [%date% %time%] Pipeline started >> "%LogFile%"

:: Verify the scripts directory exists
if not exist "%ScriptDir%" (
echo [ERROR] Scripts directory not found: %ScriptDir%
pause
exit /b 1
)

:: STAGE 1
echo [STAGE 1/3] Initializing Environment...
call "%ScriptDir%\01_init.bat"
if %errorlevel% neq 0 (
echo [ERROR] Stage 1 failed with exit code: %errorlevel%
echo [%date% %time%] FAILED at Stage 1 >> "%LogFile%"
pause
exit /b 1
)

:: STAGE 2
echo [STAGE 2/3] Fetching Data...
call "%ScriptDir%\02_fetch.bat"
if %errorlevel% neq 0 (
echo [ERROR] Stage 2 failed with exit code: %errorlevel%
echo [%date% %time%] FAILED at Stage 2 >> "%LogFile%"
pause
exit /b 1
)

:: STAGE 3
echo [STAGE 3/3] Generating Reports...
call "%ScriptDir%\03_reports.bat"
if %errorlevel% neq 0 (
echo [ERROR] Stage 3 failed with exit code: %errorlevel%
echo [%date% %time%] FAILED at Stage 3 >> "%LogFile%"
pause
exit /b 1
)

echo.
echo [SUCCESS] Pipeline complete. All 3 stages finished.
echo [%date% %time%] Pipeline completed successfully >> "%LogFile%"

pause
endlocal

Method 2: Conditional Chaining (Success/Fail)

Sometimes you only want to run the next script if the previous one succeeded. You can use the && operator for this. Conversely, || runs a command only when the previous one fails.

@echo off
setlocal

echo [PIPELINE] Running conditional chain...

:: Run stage2 only if stage1 succeeds (exit code 0)
call "%~dp0stage1_backup.bat" && call "%~dp0stage2_upload.bat"

:: Check the final result
if %errorlevel% equ 0 (
echo [SUCCESS] All stages completed.
) else (
echo [ERROR] Pipeline failed. Running error handler...
call "%~dp0handle_error.bat"
)

pause
endlocal
tip

By using &&, you create a "Safety Chain." If the database backup (Stage 1) fails, the script will not attempt to upload the backup (Stage 2), preventing corrupted or missing data from being sent to the destination.

Passing Arguments Through the Chain

You can pass arguments from the master script down to the children just like passing parameters from the command line.

@echo off
setlocal

set "TargetProject=BluePhoenix"
set "LogFile=%~dp0pipeline.log"

:: Pass variables as arguments to child scripts
call "%~dp0process_data.bat" "%TargetProject%" "%LogFile%"

if %errorlevel% neq 0 (
echo [ERROR] Data processing failed for project: %TargetProject%
)

endlocal

Inside the child script (process_data.bat), access the values as %~1 and %~2:

@echo off
setlocal
set "Project=%~1"
set "Log=%~2"

echo [%date% %time%] Processing project: %Project% >> "%Log%"
:: Processing logic here...

endlocal
exit /b 0

How to Avoid Common Errors

Wrong Way: Absolute Paths in Hardcoded Scripts

If you write call C:\Users\Admin\Desktop\scripts\tool.bat, your script will break as soon as you move it to another machine.

Correct Way: Use the relative path variable %~dp0, which represents the directory of the currently running script. call "%~dp0subscripts\tool.bat"

Problem: Variable Pollution

If Script 1 sets a variable named TARGET, and Script 2 also uses TARGET, Script 2 might inherit the wrong value.

Best Practice: Use setlocal at the beginning of every child script to ensure its variables don't "leak" back into the master or other scripts in the chain.

Problem: Ignoring child script exit codes

If you run call child.bat without checking %errorlevel%, a failed child script will be silently ignored and the master will continue with corrupted or missing data.

Best Practice: Check %errorlevel% after every call statement (as shown in Method 1).

Best Practices and Rules

1. Modular Design

Keep your scripts small. A "Database Backup" script should only back up the database. If you need to zip the files afterward, do that in a separate script chained via the master. This makes debugging much faster.

2. Error Reporting

Each script in the chain should return a specific exit code (exit /b 0 for success, exit /b 1 for failure). The master script should check these codes and halt the chain if a critical error occurs (as demonstrated in Method 1).

3. Shared Logging

Pass a log file path through the chain so all scripts write to the same file. This creates a unified timeline of the entire pipeline.

call "%~dp0stage1.bat" "%LogFile%"
call "%~dp0stage2.bat" "%LogFile%"

Conclusions

Chaining Batch scripts together is the most effective way to scale your Windows automation. By mastering the CALL command and utilizing conditional logic with &&, you can transform a collection of simple tasks into a powerful, resilient pipeline. This modular approach not only keeps your code clean but also ensures that your complex workflows scale reliably across different environments.