2

I am working on multiple batch files and I want them to share some variables, so I created a batch file that has all these setups SetupEnv:

rem General setup
:: To pause or not after running a batch file
SET isPause = true

:: The directory where your source code is located
SET directory = D

:: The folders where your primary & secondary source code is located
:: I like to have two source code folders, if you don't then just have them pointing to the same folder
SET primary_source_code = \Dev\App
SET secondary_source_code = \Dev\App2

:::::::::::::::::::::::::::::::::::::::::::: XAMPP :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
rem If you're using XAMPP then set these up
:: Your destination folder
SET base_destination = C:\xampp\htdocs

:: The base url that is pointing to your destination folder (in most cases it's localhost)
SET base_url = http://10.0.2.65

:::::::::::::::::::::::::::::::::::::::::: Angular :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
rem If you're using angular set these up
:: The folder where you built code is copied
SET build_file = dist

And from another batch file I'm calling that file first:

::setup
call ../SetupEnv

echo %directory% dir
pause;

The problem is that even though the file runs smoothly and I can see in the outputs that things are being setup, the variables are not coming across to the file I'm calling it from. So in that example %directory% is not being printed.

EDIT I also tried using Joey's answer:

::setup
for /f "delims=" %%x in (../SetupEnv.txt) do (set "%%x")

echo %directory% dir
pause

But that didn't work either and %directory% didn't get printed

Naguib Ihab
  • 4,259
  • 7
  • 44
  • 80
  • 1
    `call` creates a subshell, so you're setting the variables there, not the parent. – Gene Sep 11 '17 at 03:15
  • @Gene if I don't use call though it shuts down after running that batch file – Naguib Ihab Sep 11 '17 at 04:14
  • @Gene: doesn't matter, as long as there is no `setlocal`/`endlocal` involved. Naguib: remove the spaces around `=` with the `set` command. They become part of the variable name respective the value. – Stephan Sep 11 '17 at 05:48
  • @Stephan thanks for the comment Stephan, I removed the spaces around the `=` so that each set would be `SET isPause=true` but that didn't work either. `%directory%` is still not getting printed – Naguib Ihab Sep 11 '17 at 05:51

2 Answers2

1

setting variables in a called batchfile works, as long as you don't use setlocal in the called batchfile (there will be an implicite endlocal, when it returns, so the variables would get lost):

> type a.bat
set var=old
echo %var%
call b.bat
echo %var%

> type b.bat
set var=new

> a.bat

> set var=old

> echo old
old

> call b.bat

> set var=new

> echo new
new

>

for the alternative for solution, I would slightly change it to:

for /f "delims=" %%a in ('type b.bat^|findstr /bic:"set "') do %%a

This will only "execute" lines, that start with set (ignoring capitalization), so you can keep any comments inside that file.

Note: ... do set "%%a" adds another set to the line (you have already one in the file), resulting in set "set var=value", which you obviously don't want.

Stephan
  • 53,940
  • 10
  • 58
  • 91
0

May be it's a bit too late, but nevertheless. I've a loader script implementation to load a configuration file with a common format between Windows Batch and Unix Bash Shell scripts.

Format description:

# FORMAT:
#   [<attributes>] <variable>[:[<class_name>]]=<value>
#
# <attributes>:           Variable space separated attributes: export
# <variable>:             Variable name corresponding to the regex: [_a-zA-Z][_a-zA-Z0-9]*
# <class_name>:           class variant name: OSWIN | OSUNIX | BAT | SH
#   OSWIN:                Apply on Windows system including cygwin/mingw/msys subsystems.
#   OSUNIX:               Apply on Unix/Linux systems excluding cygwin/mingw/msys subsystems.
#   BAT:                  Apply on Windows system when this file has loaded from the Windows batch script loader.
#   SH:                   Apply on any system when this file has loaded from the Bash shell script loader.
#
# <value>:                Can start by the `"` quote character, but two quotes does remove only when exist on both ends of a value.
#

Note: The export attribute has meaning only in the Unix Shell parser.

config file example:

export PYTHON_EXE_PATH:OSWIN="c:/python/x86/38/python.exe"
export PYTHON_EXE_PATH:OSUNIX=python3

export PYTHONDONTWRITEBYTECODE=1

MY_SHELL_SCRIPT:BAT=blabla.bat
MY_SHELL_SCRIPT:SH=blabla.sh

usage example:

call load_config.bat . . myvars.vars

This will generate the myvars.vars from the myvars.vars.in file and load it.

The script does generate an instance configuration file from a template file before parse an instance file. Implementation a bit complicated and might change in the future:

https://github.com/andry81/contools/tree/HEAD/Scripts/Tools/build/load_config.bat https://github.com/andry81/contools/tree/HEAD/Scripts/Tools/build/.load_config

CAUTION:

Seems the stackoverflow incorrectly handles tabulation characters (and loses other characters like \x01) in the copy-pasted code, so the below code might not work if you copy it directly by CTRL+C. Use links above to directly download the script.

Old implementation (just for example):

@echo off

setlocal DISABLEDELAYEDEXPANSION

set "__CONFIG_IN_DIR=%~1"
set "__CONFIG_OUT_DIR=%~2"
set "__CONFIG_FILE=%~3"

if not defined __CONFIG_IN_DIR (
  echo.%~nx0: error: input config directory is not defined.
  exit /b 1
) >&2

if not defined __CONFIG_OUT_DIR (
  echo.%~nx0: error: output config directory is not defined.
  exit /b 2
) >&2

set "__CONFIG_IN_DIR=%__CONFIG_IN_DIR:\=/%"
set "__CONFIG_OUT_DIR=%__CONFIG_OUT_DIR:\=/%"

if "%__CONFIG_IN_DIR:~-1%" == "/" set "__CONFIG_IN_DIR=%__CONFIG_IN_DIR:~0,-1%"
if "%__CONFIG_OUT_DIR:~-1%" == "/" set "__CONFIG_OUT_DIR=%__CONFIG_OUT_DIR:~0,-1%"

if not exist "%__CONFIG_IN_DIR%\" (
  echo.%~nx0: error: input config directory does not exist: "%__CONFIG_IN_DIR%".
  exit /b 10
) >&2

if not exist "%__CONFIG_OUT_DIR%\" (
  echo.%~nx0: error: output config directory does not exist: "%__CONFIG_OUT_DIR%".
  exit /b 11
) >&2

if not exist "%__CONFIG_OUT_DIR%\%__CONFIG_FILE%" ^
if exist "%__CONFIG_IN_DIR%/%__CONFIG_FILE%.in" (
  echo."%__CONFIG_IN_DIR%/%__CONFIG_FILE%.in" -^> "%__CONFIG_OUT_DIR%/%__CONFIG_FILE%"
  type "%__CONFIG_IN_DIR:/=\%\%__CONFIG_FILE%.in" > "%__CONFIG_OUT_DIR%/%__CONFIG_FILE%"
)

rem load configuration files
if not exist "%__CONFIG_OUT_DIR%/%__CONFIG_FILE%" (
  echo.%~nx0: error: config file is not found: "%__CONFIG_OUT_DIR%/%__CONFIG_FILE%".
  exit /b 20
) >&2

for /F "usebackq eol=# tokens=* delims=" %%i in ("%__CONFIG_OUT_DIR%/%__CONFIG_FILE%") do (
  endlocal
  setlocal DISABLEDELAYEDEXPANSION
  for /F "eol=# tokens=1,* delims==" %%j in ("%%i") do (
    set "__VAR=%%j"
    set "__VALUE=%%k"
    call :PARSE_EXPR && (
      setlocal ENABLEDELAYEDEXPANSION
      for /F "tokens=1,* delims==" %%i in ("!__VAR!=!__VALUE!") do (
        endlocal
        endlocal
        set "%%i=%%j"
      )
      type nul>nul
    ) || endlocal
  )
)

exit /b 0

:PARSE_EXPR
if not defined __VAR exit /b 1

rem CAUTION:
rem Inplace trim of surrounded white spaces ONLY from left and right sequences as a whole for performance reasons.
rem

:TRIM_VAR_NAME
:TRIM_VAR_NAME_LEFT_LOOP
if not defined __VAR exit /b 1
if not ^%__VAR:~0,1%/ == ^ / if not ^%__VAR:~0,1%/ == ^ / goto TRIM_VAR_NAME_RIGHT_LOOP
set "__VAR=%__VAR:~1%"
goto TRIM_VAR_NAME_LEFT_LOOP

:TRIM_VAR_NAME_RIGHT_LOOP
if not ^%__VAR:~-1%/ == ^ / if not ^%__VAR:~-1%/ == ^   / goto TRIM_VAR_NAME_RIGHT_LOOP_END
set "__VAR=%__VAR:~0,-1%"
if not defined __VAR exit /b 1
goto TRIM_VAR_NAME_RIGHT_LOOP

:TRIM_VAR_NAME_RIGHT_LOOP_END

if not defined __VALUE exit /b 0

rem Replace a value quote characters by the \x01 character.
set "__VALUE=%__VALUE:"=%"

:TRIM_VAR_VALUE
setlocal DISABLEDELAYEDEXPANSION

:TRIM_VAR_VALUE_LEFT_LOOP
if not defined __VALUE exit /b 0
if not ^%__VALUE:~0,1%/ == ^ / if not ^%__VALUE:~0,1%/ == ^ / goto TRIM_VAR_VALUE_RIGHT_LOOP
set "__VALUE=%__VALUE:~1%"
goto TRIM_VAR_VALUE_LEFT_LOOP

:TRIM_VAR_VALUE_RIGHT_LOOP
if not ^%__VALUE:~-1%/ == ^ / if not ^%__VALUE:~-1%/ == ^   / goto TRIM_VAR_VALUE_RIGHT_LOOP_END
set "__VALUE=%__VALUE:~0,-1%"
if not defined __VALUE exit /b 0
goto TRIM_VAR_VALUE_RIGHT_LOOP

:TRIM_VAR_VALUE_RIGHT_LOOP_END
(
  endlocal
  set "__VALUE=%__VALUE%"
)

for /F "eol=     tokens=1,* delims=:" %%i in ("%__VAR%") do (
  set "__VAR=%%i"
  set "__PLATFORM=%%j"
)

if not defined __VAR exit /b 1

if defined __PLATFORM ^
if not "%__PLATFORM%" == "BAT" ^
if not "%__PLATFORM%" == "WIN" ^
if not "%__PLATFORM%" == "OSWIN" exit /b 1

for /F "eol=# tokens=1,* delims=     " %%i in ("%__VAR%") do (
  set "__ATTR=%%i"
  set "__VAR=%%j"
)

if not defined __VAR (
  set "__VAR=%__ATTR%"
  set "__ATTR="
)

if not defined __VAR exit /b 1

if ^/ == ^%__VALUE:~1,1%/ goto PREPARSE_VALUE
if not ^/ == ^%__VALUE:~0,1%/ goto PREPARSE_VALUE
if not ^/ == ^%__VALUE:~-1%/ goto PREPARSE_VALUE

:REMOVE_QUOTES
for /F "tokens=* delims=" %%i in ("%__VALUE:~1,-1%") do set "__VALUE=%%i"

if not defined __VALUE exit /b 0

goto PARSE_VALUE

:PREPARSE_VALUE
set __HAS_VALUE=0
for /F "eol=# tokens=* delims=" %%i in ("%__VALUE%") do set "__HAS_VALUE=1"

if %__HAS_VALUE% EQU 0 (
  set "__VALUE="
  exit /b 0
)

:PARSE_VALUE
rem recode quote and exclamation characters
set "__ESC__=^"
set __QUOT__=^"
set "__EXCL__=!"
set "__VALUE=%__VALUE:!=!__EXCL__!%"
set "__VALUE=%__VALUE:^=!__ESC__!%"
set "__VALUE=%__VALUE:=!__QUOT__!%"

exit /b 0
Andry
  • 2,273
  • 29
  • 28