Search code examples
windowsscriptingbatch-processinggoto

Windows Batch Scripting - GOTO branching doesn't work as expected


I have created a batch script that synchronizes the folder structure from production to all lower environments. Using robocopy, I clean the folders in lower environments and copy over just the folders and sub folders (minus the files to save space). It works as expected.

Now I'm trying to consolidate the scripts (1 script / environment) into 1 so it takes the environment name as an argument and triggers just the code that is relevant for that environment. I've written multiple IF GOTO statements for branching the flow of execution but I've hit a snag and it's just not working. I could most certainly do with another pair of expert eyes to spot the mistake and help fix it. Please find the script below: Now it asks for the inputs and then executes END statement straight away and ends. Many thanks in advance.

@echo off

set /p env = "Enter Target Environment (EnvA, EnvB, EnvC, EnvF): "

if "%env%" == "EnvA" goto :SyncA
if "%env%" == "EnvB" goto :SyncB
if "%env%" == "EnvC" goto :SyncC
if "%env%" == "EnvF" goto :SyncF

:SyncA
cls

echo *******************************************************************************************
echo * Delete Environment A SAN share contents and resync folder structure from production *
echo *******************************************************************************************

set sd=C:\mockdev\Build
set dd=\\testA\TempStorage\BuildEdge
set ipasd=C:\mockdev\Environments
set ipadd=\\testA\TempStorage\Environments
set copy_options=/MIR /XF * /R:3 /W:10
set log_options=/NP /NFL /NDL /NJH
set error=0
set result=0

if not exist "%sd%" echo ERROR: [%sd%] does not exist
if not exist "%dd%" echo ERROR: [%dd%] does not exist

echo This script will delete all files in [%dd%] and resync the folder structure from [%sd%]
echo Continue?

Pause

echo Deleting all files from [%dd%] ...
del %dd%\*.* /s /q

echo Recreating [%dd%] folder structure from [%sd%] ...

Pause

Robocopy %sd% %dd% %copy_options% %log_options% 

Mkdir \\testA\TempStorage\BuildEdge\IpaB
robocopy %ipasd% %ipadd% %copy_options% %log_options%

if ERRORLEVEL 16 set result=*ERROR* Fatal error (Error: %ERRORLEVEL%)
if ERRORLEVEL  8 set result=*ERROR* General failure (Error: %ERRORLEVEL%)
if ERRORLEVEL  4 set result=*WARNING* Check log for possible errors (Error: %ERRORLEVEL%)
set result=*OK* Job completed successfully (%ERRORLEVEL%)

echo ------------------------------------------------------------------------------
echo Script complete [%result%]

exit /b %error%

goto end

:SyncB
cls

echo *******************************************************************************************
echo * Delete Environment B SAN share contents and resync folder structure from production *
echo *******************************************************************************************

set sd=C:\mockdev\Build
set dd=\\testB\TempStorage\BuildEdge
set ipasd=C:\mockdev\Environments
set ipadd=\\testB\TempStorage\Environments
set copy_options=/MIR /XF * /R:3 /W:10
set log_options=/NP /NFL /NDL /NJH
set error=0
set result=0

if not exist "%sd%" echo ERROR: [%sd%] does not exist
if not exist "%dd%" echo ERROR: [%dd%] does not exist

echo This script will delete all files in [%dd%] and resync the folder structure from [%sd%]
echo Continue?

Pause

echo Deleting all files from [%dd%] ...
del %dd%\*.* /s /q

echo Recreating [%dd%] folder structure from [%sd%] ...

Pause

Robocopy %sd% %dd% %copy_options% %log_options% 

Mkdir \\testB\TempStorage\BuildEdge\IpaB
robocopy %ipasd% %ipadd% %copy_options% %log_options%

if ERRORLEVEL 16 set result=*ERROR* Fatal error (Error: %ERRORLEVEL%)
if ERRORLEVEL  8 set result=*ERROR* General failure (Error: %ERRORLEVEL%)
if ERRORLEVEL  4 set result=*WARNING* Check log for possible errors (Error: %ERRORLEVEL%)
set result=*OK* Job completed successfully (%ERRORLEVEL%)

echo ------------------------------------------------------------------------------
echo Script complete [%result%]

exit /b %error%

goto end

:SyncC
cls

echo *******************************************************************************************
echo * Delete Environment C SAN share contents and resync folder structure from production *
echo *******************************************************************************************

set sd=C:\mockdev\Build
set dd=\\testC\TempStorage\BuildEdge
set ipasd=C:\mockdev\Environments
set ipadd=\\test02\TempStorage\Environments
set copy_options=/MIR /XF * /R:3 /W:10
set log_options=/NP /NFL /NDL /NJH
set error=0
set result=0

if not exist "%sd%" echo ERROR: [%sd%] does not exist
if not exist "%dd%" echo ERROR: [%dd%] does not exist

echo This script will delete all files in [%dd%] and resync the folder structure from [%sd%]
echo Continue?

Pause

echo Deleting all files from [%dd%] ...
del %dd%\*.* /s /q

echo Recreating [%dd%] folder structure from [%sd%] ...

Pause

Robocopy %sd% %dd% %copy_options% %log_options% 

Mkdir \\testC\TempStorage\BuildEdge\IpaB
robocopy %ipasd% %ipadd% %copy_options% %log_options%

if ERRORLEVEL 16 set result=*ERROR* Fatal error (Error: %ERRORLEVEL%)
if ERRORLEVEL  8 set result=*ERROR* General failure (Error: %ERRORLEVEL%)
if ERRORLEVEL  4 set result=*WARNING* Check log for possible errors (Error: %ERRORLEVEL%)
set result=*OK* Job completed successfully (%ERRORLEVEL%)

echo ------------------------------------------------------------------------------
echo Script complete [%result%]

exit /b %error%

goto end

:SyncF
cls

echo *******************************************************************************************
echo * Delete Environment F SAN share contents and resync folder structure from production *
echo *******************************************************************************************

set sd=C:\mockdev\Build
set dd=\\testF\TempStorage\BuildEdge
set ipasd=C:\mockdev\Environments
set ipadd=\\testF\TempStorage\Environments
set copy_options=/MIR /XF * /R:3 /W:10
set log_options=/NP /NFL /NDL /NJH
set error=0
set result=0

if not exist "%sd%" echo ERROR: [%sd%] does not exist
if not exist "%dd%" echo ERROR: [%dd%] does not exist

echo This script will delete all files in [%dd%] and resync the folder structure from [%sd%]
echo Continue?

Pause

echo Deleting all files from [%dd%] ...
del %dd%\*.* /s /q

echo Recreating [%dd%] folder structure from [%sd%] ...

Pause

Robocopy %sd% %dd% %copy_options% %log_options% 

Mkdir \\testF\TempStorage\BuildEdge\IpaB
robocopy %ipasd% %ipadd% %copy_options% %log_options%

if ERRORLEVEL 16 set result=*ERROR* Fatal error (Error: %ERRORLEVEL%)
if ERRORLEVEL  8 set result=*ERROR* General failure (Error: %ERRORLEVEL%)
if ERRORLEVEL  4 set result=*WARNING* Check log for possible errors (Error: %ERRORLEVEL%)
set result=*OK* Job completed successfully (%ERRORLEVEL%)

echo ------------------------------------------------------------------------------
echo Script complete [%result%]

exit /b %error%

goto end

:end
Press any key to exit
pause>nul
Exit

Solution

  • set /p env = "Enter Target Environment (EnvA, EnvB, EnvC, EnvF): "
    ----------^ This space gets included into the variable name
    

    Change to

    set /p "env=Enter Target Environment (EnvA, EnvB, EnvC, EnvF): "
    

    This itself renders the selection invalid.

    If the only difference between the environments can be moved to variables, don't duplicate the code, just the variable assignment. It is easier to maintain

    In this sample, for each environment the general configuration is called and then the specific variables for the environment are set. That way, if for any reason any of the environment need to overwrite a general configuration, it can be done. Once all the variables are property configured, the file management process is started.

    @echo off
        setlocal enableextensions
    
    :ask    
    
        set "env="
        echo(
        set /p "env=Enter Target Environment (EnvA, EnvB, EnvC, EnvF): "
    
               if /i "%env%"=="EnvA" ( call :SyncA 
        ) else if /i "%env%"=="EnvB" ( call :SyncB 
        ) else if /i "%env%"=="EnvC" ( call :SyncC 
        ) else if /i "%env%"=="EnvF" ( call :SyncF 
        ) else set "env="
    
        if defined env goto :doWork
    
        goto :ask
    
    :SyncConfig
        set "sd=C:\mockdev\Build"
        set "ipasd=C:\mockdev\Environments"
        set "copy_options=/MIR /XF * /R:3 /W:10"
        set "log_options=/NP /NFL /NDL /NJH"
        set "error=0"
        set "result=0"
        goto :eof
    
    :SyncA
        call :SyncConfig
        set "dd=\\testA\TempStorage\BuildEdge"
        set "ipadd=\\testA\TempStorage\Environments"
        goto :eof
    
    :SyncB
        call :SyncConfig
        set "dd=\\testB\TempStorage\BuildEdge"
        set "ipadd=\\testB\TempStorage\Environments"
        goto :eof
    
    :SyncC
        call :SyncConfig
        set "dd=\\testC\TempStorage\BuildEdge"
        set "ipadd=\\test02\TempStorage\Environments"
        goto :eof
    
    :SyncD    
        call :SyncConfig
        set "dd=\\testF\TempStorage\BuildEdge"
        set "ipadd=\\testF\TempStorage\Environments"
        goto :eof
    
    :doWork    
        cls
    
        echo *******************************************************************************************
        echo * Delete Environment %env% SAN share contents and resync folder structure from production *
        echo *******************************************************************************************
    
        if not exist "%sd%" echo ERROR: [%sd%] does not exist
        if not exist "%dd%" echo ERROR: [%dd%] does not exist
    
        echo This script will delete all files in [%dd%] and resync the folder structure from [%sd%]
        echo Continue?
    
        Pause
    
        echo Deleting all files from [%dd%] ...
        del %dd%\*.* /s /q
    
        echo Recreating [%dd%] folder structure from [%sd%] ...
    
        Pause
    
        Robocopy %sd% %dd% %copy_options% %log_options% 
    
        Mkdir "%dd%\IpaB"
        robocopy %ipasd% %ipadd% %copy_options% %log_options%
    
                if ERRORLEVEL 16 ( set "error=%errorlevel%" & set "result=*ERROR* Fatal error (Error: %ERRORLEVEL%)"
        ) else  if ERRORLEVEL  8 ( set "error=%errorlevel%" & set "result=*ERROR* General failure (Error: %ERRORLEVEL%)"
        ) else  if ERRORLEVEL  4 ( set "error=%errorlevel%" & set "result=*WARNING* Check log for possible errors (Error: %ERRORLEVEL%)"
        ) else                     set "error=%errorlevel%" & set "result=*OK* Job completed successfully (%ERRORLEVEL%)"
    
        echo(------------------------------------------------------------------------------
        echo(Script complete [%result%]
    
        Press any key to exit
        pause>nul
        endlocal & exit /b %error%