I have a Batch script in which I want to get the full path to the script. I'm curious, is there any difference between this:
set scriptpath=%0
and this:
set scriptpath=%~f0
Thanks for helping.
%0
references argument 0 – the name of the batch file – always exactly as specified on command line or in another batch file.
So if a batch file named Test.bat
stored in C:\Temp
is started for example from within a command prompt window with current directory being C:\
with an execution of temp\test
, then %0
is substituted by temp\test
on execution of the batch file.
But %~f0
is substituted nearly always by the batch file name with file extension and with complete path – fully qualified file name – and always without double quotes even if the file name or the path contains one or more characters like space or &()[]{}^=;!'+,`~
usually requiring the usage of double quotes.
Therefore the batch file Test.bat
stored in C:\Temp
with the lines
@echo %0
@echo %~f0
started from within a command prompt window with "temp\test.bat"
with current directory being C:\
outputs:
"temp\test.bat"
C:\Temp\Test.bat
There can bee seen here all differences:
A description of %~f0
and other modifiers can be read in help of command CALL output on running call /?
or in help of command FOR on running for /?
in a command prompt window and reading all displayed pages.
Note 1:
The fully qualified batch file name should be assigned to an environment variable if needed later in batch file and the current directory is modified from within the batch file using either CD or PUSHD. For the reason see the answers on What is the reason for batch file path referenced with %~dp0 sometimes changes on changing directory?
Note 2:
Running example batch file above from C:\
just with "temp\test"
results in the output:
"temp\test"
C:\Temp\Test
The file extension is missing which is caused by the cmd
bug described in the referenced topic of first note. Starting the batch file with temp\test
without the double quotes produces the expected output:
temp\test
C:\Temp\Test.bat
The ultimate solution to get the fully qualified file name of the batch file always determined and output correct is:
@echo off
goto Main
:GetFullBatchFileName
set "%1=%~f0" & goto :EOF
:Main
setlocal EnableExtensions DisableDelayedExpansion
echo %0
call :GetFullBatchFileName FullBatchFileName
setlocal EnableDelayedExpansion & echo !FullBatchFileName!& endlocal
endlocal
This code works even for a batch file C:\Temp\Development & !Test!(!)\BestCode.bat
being executed from C:\
with "temp\development & !test!(!)\bestcode"
producing the output:
"temp\development & !test!(!)\bestcode"
C:\Temp\Development & !Test!(!)\BestCode.bat
Why using delayed expansion to output the full batch file name?
The output of a file/folder name assigned to an environment variable like FullBatchFileName
with command ECHO without surrounding "
requires the usage of delayed expansion as otherwise an ampersand in file/folder name would be interpreted as unconditional AND operator and not as literal character being part of the file/folder name to output by ECHO.
Example on what could happen on not using delayed expansion on output of a file/folder name assigned to an environment variable without surrounding "
:
@echo off
goto Main
:GetFullBatchFileName
set "%1=%~f0" & goto :EOF
:Main
setlocal EnableExtensions DisableDelayedExpansion
echo %0
call :GetFullBatchFileName FullBatchFileName
echo %FullBatchFileName%
endlocal
This batch file code stored in C:\Temp\Development & !Test!(!)\NotGood1.bat
results in execution from C:\
with "temp\development & !test!(!)\notgood1"
in the output:
"temp\development & !test!(!)\notgood1"
C:\Temp\Development
'!Test!' is not recognized as an internal or external command,
operable program or batch file.
So the Windows command processor cmd
interprets &
in the value of the environment variable FullBatchFileName
as unconditional command operator AND. For that reason ECHO outputs just the part of the fully qualified batch file name up to &
and the rest is interpreted by cmd.exe
as a second command to execute after execution of command ECHO. cmd.exe
makes in this case lots of file system accesses to find an executable or script file which could be meant by !Test!(!)\NotGood1.bat
and finally after not finding something suitable outputs the error message.
Why is delayed expansion not enabled from the beginning?
Delayed expansion cannot be enabled from the beginning as this would result in interpreting !
in file/folder name strings as beginning/end of a delayed expanded variable reference as it can be seen with the following code:
@echo off
goto Main
:GetFullBatchFileName
set "%1=%~f0" & goto :EOF
:Main
setlocal EnableExtensions EnableDelayedExpansion
set "Test="
echo %0
call :GetFullBatchFileName FullBatchFileName
echo !FullBatchFileName!
endlocal
This batch file code stored in C:\Temp\Development & !Test!(!)\NotGood2.bat
results in execution from C:\
with "temp\development & !test!(!)\notgood2"
in the output:
"temp\development & ()\notgood2"
C:\Temp\Development & ()\NotGood2.bat
It can be seen that !test!
and !Test!
and the third !
in the round brackets disappear from both output strings because of !test!
and !Test!
are interpreted as delayed expanded variable references and there is no environment variable Test
. The third !
is removed as interpreted as beginning of a delayed expanded variable reference with no matching !
marking the end of the variable name.
See also:
%~f0
causes %0
to be expanded to a fully-qualified path name. They may or may not be equivalent, depending on what the original value of %0
is.
The meanings of these modifiers are hidden in the documentation for the For command.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With