Referencing a batch file argument
Open a command prompt window and run call /?
. The output help explains how to reference batch file arguments. %1
references the first argument as passed to the batch file. That can be for example 1
(not quoted argument string), but also "1"
(quoted argument string). %~1
references first argument string with surrounding double quotes removed.
It is wrong to add one more %
after the argument reference. The syntax %variable%
is used to reference the string value of an environment variable. Batch file arguments are referenced only with percent sign and digit without or with a modifier between. There is no more percent sign after the digit. That is also the reason why 1
, 2
, 3
, ... are not possible as names for environment variables.
So not good is IF "%1%" == "0" (
because of this can result on batch file called with "1"
as first argument in execution of the command line:
IF ""1"" == "0" (
The much better syntax is IF "%~1" == "0" (
which results in execution of the command line:
IF "1" == "0" (
See my answer on difference between “…” and x“…” in batch for more details on how to evaluate batch file arguments.
Appending a folder path to local PATH
The environment variable PATH
holds a comma-separated list of folder paths whereby the list separator is a semicolon instead of a comma.
Therefore a ;
at end of PATH
means there is one more folder path which is an empty folder path. It is possible to specify an empty folder path in the middle or at end of PATH
, but it is bad practice to do so because of PATH
should not contain empty folder paths.
For that reason the following command line in your code is not good:
if errorlevel 1 SET "PATH=%PATH%%cd%\App0;"
There is also missing ;
in case of PATH
does not already end with a semicolon which could be a reason for the error message on second execution of the batch file.
The better code can be seen below on completely revised batch file code.
Referencing current directory
It is possible to reference the current directory with %CD%
which can differ from batch file directory referenced with %~dp0
. %~dp0
references drive and path of argument 0 which is the batch file itself. The batch file path string referenced with %~dp0
always ends with a backslash. Therefore no additional backslash should be used after %~dp0
on concatenating it with a file/folder name.
The dynamic environment variable CD
ends usually with no backslash at end. So in most cases %CD%
must be concatenated with an additional \
with a file/folder name. But there is one exception which must be taken into account on using %CD%
in a batch file: %CD%
expands to a string with \
at end on current directory being the root directory of a drive, for example C:\
or D:\
. So it is always necessary on using %CD%
to check if the string already ends with a backslash before appending a file/folder name without or with an additional backslash.
Other recommendations
The usage of a command block starting with (
and ending with )
should be avoided on using environment variables defined/modified within a command block and referenced within the command block as this requires the usage of delayed expansion as explained by help output on running set /?
in a command prompt window on an IF and a FOR example on which command blocks are used usually. The Windows command processor is designed primary for executing one command line after the other. The usage of command blocks can speed up the execution of a batch file in some cases, but in many cases it is better to avoid them.
See debugging a batch file with a short description how to debug a batch file. A single step execution is not really possible. But cmd.exe
shows on which line or command block an error occurred resulting in exiting batch file execution and what is the error.
Revised batch file code
Here is the revised batch file code:
@echo off
goto Main
:AddPath
echo %PATH%;|%SystemRoot%\System32\findstr.exe /I /C:"\%~1;" >nul 2>&1
if not errorlevel 1 echo Found %~1 in PATH& goto :EOF
set "Separator=;"
if "%PATH:~-1%" == ";" set "Separator="
if "%CD:~-1%" == "\" (set "AppPath=%CD%%~1") else set "AppPath=%CD%\%~1"
set "PATH=%PATH%%Separator%%AppPath%"
set "AppPath="
set "Separator="
goto :EOF
:Main
if "%~1" == "0" call :AddPath App0 & goto errorBypass
if "%~1" == "1" call :AddPath App1 & goto errorBypass
if not "%~1" == "" goto RunApp
if "%HUMBER_HOME%" == "" goto Error2
if exist "%HUMBER_HOME%\bin\setEnv.bat" (
call "%HUMBER_HOME%\bin\setEnv.bat"
goto errorBypass
)
echo File "setEnv.bat" in subdirectory "bin" in directory
echo defined by environment variable HUMBER_HOME not found.
echo HUMBER_HOME directory: "%HUMBER_HOME%"
echo/
pause
goto :EOF
:RunApp
echo HERE
goto :EOF
:Error2
echo Error2
goto :EOF
:errorBypass
if exist "run.bat" call "run.bat"
There is defined the subroutine AddPath
at top of the batch file which is a bit unusual. So the second line with goto Main
results in jumping over code of the subroutine on starting the execution of the batch file.
The subroutine AddPath
is called with either App0
or App1
on first argument being 0
or "0"
or 1
or "1"
.
The first line in AddPath
outputs current value of local environment variable PATH
with a semicolon appended and redirects this output to FINDSTR which searches case-insensitive and literally for the first argument string passed to the subroutine after a backslash and ending with a semicolon. The additional \
and ;
should avoid a false positive on any folder path in PATH
containing by chance also App0
or App1
somewhere in the middle of the folder path. This small enhancement is not 100% fail safe, but should be good enough.
FINDSTR exits with 0
on searched string found in line. In this case just an information message is output and the subroutine is exited which results in batch file execution being continued on main code on which the subroutine was called before. Otherwise the passed application name must be added to local PATH
.
See also:
So first the environment variable Separator
is defined with ;
as value. But if local PATH
already ends with a backslash although it should not, the environment variable is deleted immediately. Please note that the command line comparing last character of PATH
with ;
can fail if PATH
ends with "
. So this simple version is not 100% fail safe.
Next the current directory path is concatenated with the passed application folder name without or with an additional backslash depending on current directory being root directory of a drive or a subdirectory of any directory.
Then the local PATH
is extended with appending the application path according to passed argument without or with an additional semicolon before.
Finally the no longer needed environment variables Separator
and AppPath
are deleted before exiting the subroutine.
A main mistake in main code as posted in question are the missing percent signs around environment variable HUMBER_HOME
on calling batch file setEnv.bat
in subdirectory bin
of the directory assigned to environment variable HUMBER_HOME
. This could be another reason for the error message on second execution of the batch file.
The revised code first checks if each batch file to call really exists before calling it.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
echo /?
findstr /?
goto /?
if /?
pause /?
set /?