Reputation: 559
On batch scripting, struggling with the %~dp0
.
The problem is that in some parts of my script, %~dp0
returns what it is supposed to return, ie the full path with drive of the folder containing the script that is running (here : 'C:\Data\name\App\App\'). In some other parts of the code, %~dp0
returns only the drive containing the script (here : 'C:\').
Here is my script (first batch script ever :D):
@ECHO OFF
ECHO.
:: run the script with the command new-built.bat /all -arch x86 -config release
SETLOCAL EnableDelayedExpansion
SET options=arch version config
SET what_to_build=all lib
:: the three following lines returns what is expected
echo %%~dp0 is returning : %~dp0
echo %%~p0 is returning : %~p0
echo %%~d0 is returning : %~d0
echo The absolute path to this script is : %~dp0%0
:: read what to build, ie all or lib only
FOR %%i in (%what_to_build%) do if %1==/%%i (
SHIFT
GOTO %%i
)
::the following sections (:readoptions and :optlp) work together to collect the options entered in the command, used to launch this script. It saves the values the two arrays "options" and "what_to_build" array
:readoptions
echo Entered the read options label
rem -- initialises variables arch, version and config with empty string
FOR %%i IN (%options% badoptions) DO (SET %%i=)
:optlp
echo Entered the read options loop
SET _parm1=%1
IF NOT DEFINED _parm1 GOTO :END
IF DEFINED _parm1 FOR %%i IN (%options%) DO IF .%_parm1%==.-%%i SET %%i=%2
IF DEFINED %%i shift&shift&(SET _parm1=)
IF DEFINED _parm1 SET badoptions=%badoptions% %1&SHIFT
GOTO :optlp
:all
echo Entered the all label ...
CALL :readoptions %*
echo About to build complete app for x86 in release config
set CYGWIN_DIR="%~dp0"
:: I want this line to return "C:\Data\name\App\App\" without quotes, but it's returning "C:\"
echo Cygwin dir (not returning what I want): %CYGWIN_DIR%
rem build lib
call %~dp0\build_scripts\build_lib_x86.bat
rem build the Visual Studio Solution
start "Build App x86 - release config" /W "%~dp0%build_scripts\build_app_x86_release.bat"
goto :end
:END
echo Program is done
endlocal
Here is the trace I get :
%~dp0 is returning : C:\Data\name\App\App\
%~p0 is returning : \Data\name\App\App\
%~d0 is returning : C:
The absolute path to this script is : C:\Data\name\App\App\new-build.bat
Entered the all label ...
Entered the read options label
Entered the read options loop
Entered the read options loop
Entered the read options loop
Entered the read options loop
Entered the read options loop
Entered the read options loop
Program is done
About to build complete app for x86 in release config
Cygwin dir (not returning what I want) : "C:\"
The system cannot find the path specified.
Program is done
There must be something happening, that I am missing. Any help would be highly appreciated.
Best
Upvotes: 1
Views: 2205
Reputation: 80113
Ooooh - Big troublez!
@ECHO OFF
ECHO.
:: run the script with the command new-built.bat /all -arch x86 -config release
SETLOCAL EnableDelayedExpansion
SET options=arch version config
SET what_to_build=all lib
:: the three following lines returns what is expected
echo %%~dp0 is returning : %~dp0
echo %%~p0 is returning : %~p0
echo %%~d0 is returning : %~d0
echo The absolute path to this script is : %~dp0%0
Given new-built.bat /all -arch x86 -config release
then %1
is /all
:: read what to build, ie all or lib only
FOR %%i in (%what_to_build%) do if %1==/%%i (
SHIFT
GOTO %%i
)
SO, since %1
is /all
, this will arrive at :all
with %1=-arch %2=x86 %3=-config %4=release
BUT %*=/all -arch x86 -config release
HAD %1
been /lib
then ditto, but will arrive at :lib
BUT for any other value of %1, processing would just charge straight on through here to the next statement....
:all
with %1=-arch %2=x86 %3=-config %4=release
BUT %*=/all -arch x86 -config release
:all
echo Entered the all label ...
CALL :readoptions %*
Since :readoptions is CALLed with %*
each of the ORIGINAL parameters is passed to :readoptions BUT instead of goto :EOF
you've modified this to 'goto ENDand hence the message
Program is doneis displayed - and processing returns to the statement following the
CALL`
echo About to build complete app for x86 in release config
set CYGWIN_DIR="%~dp0"
:: I want this line to return "C:\Data\name\App\App\" without quotes, but it's returning "C:\"
echo Cygwin dir (not returning what I want): %CYGWIN_DIR%
rem build lib
call %~dp0\build_scripts\build_lib_x86.bat
rem build the Visual Studio Solution
start "Build App x86 - release config" /W "%~dp0%build_scripts\build_app_x86_release.bat"
I believe that you would actually want CYGWIN_DIR to be assigned the value of the name of your CYGWIN directory. Likely we could work this out, but far better if it's set permanently in your environment. The easy way to do this is:
SETX CYGWIN_DIR "wherever your cygwin dir is"
SETX CYGWIN_DIR "wherever your cygwin dir is" /M
(the first assigns the value for NEW CMD instances in your current LOGON session, the second for future logon sessions. IOW, execute the second and reboot... You can delete the entry if you wish by using SETX CYGWIN_DIR "" )
@ECHO OFF
ECHO.
:: run the script with the command new-built.bat /all -arch x86 -config release
SETLOCAL EnableDelayedExpansion
SET options=arch version config
SET SLASHOPTS=ALL LIB
(SET SWITCHES=)
:: %CD% is the magic pseudovariable for the current directory.
:: quote it if you wish
SET CYGWIN_DIR=%CD%
:: The above line of course only if you want CYGWIN_DIR to be set to the current directory
CALL :READOPTIONS %*
:: NOTE THAT %badoptions% now contains a list of the items NOT
:: involved in the OPTIONS, SWITCHES or SLASHOPTIONS
:: read what to build, ie all or lib only
:: ONE WAY...
IF DEFINED ALL goto ALL
IF DEFINED LIB goto LIB
:: ANOTHER WAY to do the same thing
for %%i in (%SLASHOPTS%) DO if defined %%i goto %%i
:: EEK! Neither ALL not LIB was specified - what to do?
echo EEK! Neither ALL not LIB was specified - exiting!
goto :EOF
:all
echo Entered the all label ...
echo About to build complete app for x86 in release config
echo Cygwin dir (not returning what I want): %CYGWIN_DIR%
rem build lib
:: I'll assume %CYGWIN_DIR%\build_scripts is where you're keeping this batch
call %CYGWIN_DIR%\build_scripts\build_lib_x86.bat
rem build the Visual Studio Solution
start "Build App x86 - release config" /W "%CYGWIN_DIR%\build_scripts\build_app_x86_release.bat"
goto end
:LIB
echo LIB processing not yet defined
goto end
:END
echo Program is done
endlocal
:readoptions
echo Entered the read options label
rem -- initialises variables arch, version and config with empty string
:readoptions
FOR %%i IN (%options% %slashopts% %switches% badoptions) DO (SET %%i=)
:optlp
SET _parm1=%1
IF NOT DEFINED _parm1 GOTO :EOF
FOR %%i IN (%switches%) DO IF /i %_parm1%==-%%i SET %%i=Y&(SET _parm1=)
IF NOT DEFINED _parm1 shift&GOTO :optlp
FOR %%i IN (%slashopts%) DO IF /i %_parm1%==/%%i SET %%i=Y&(SET _parm1=)
IF NOT DEFINED _parm1 shift&GOTO :optlp
FOR %%i IN (%options%) DO IF /i %_parm1%==-%%i (
SET %%i=%2
IF DEFINED %%i shift&shift&(SET _parm1=)
)
IF DEFINED _parm1 SET badoptions=%badoptions% %1&SHIFT
GOTO :optlp
Note that I've slightly modified :readoptions so that you can set -option anoptionvalue
or -switch
or /slashoption
Note also that you could transfer the section from :readoptions through to the end to an independent batch file, say readoptions.bat
and place that file anywhere on your path
(see set path
from the prompt) and then ANY batch could execute
CALL READOPTIONS %*
to read your options/switches/slashoptions as you've individually specified them in the variables options
, switches
and slashopts
in your batch - and badoptions
will contain any remaining parameters...
(Note on colons:
call :routine parameterlist
calls an INTERNAL routine with 'private' parameters parameterlist
call routine parameterlist
calls an EXTERNAL routine with 'private' parameters parameterlist
; ie. the [batch] file 'routinefrom somewhere on the
path`
goto :eof
Is an inbuilt facility to go to the physical end-of-file. This terminates a CALL and returns to the line following OR exits the batch completely. )
Upvotes: 1