Myna
Myna

Reputation: 559

%~dp0 not returning folder containing the running script

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

Answers (1)

Magoo
Magoo

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....


...so we arrive at :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 messageProgram is doneis displayed - and processing returns to the statement following theCALL`

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"


Let's start afresh...

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 thepath`

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

Related Questions