Returning to the original effect regarding quotes around the command.
jeb wrote:This seems to be a problem, that cmd.exe can start the file, but doesn't remove the quotes correctly.
I'm not convinced. Enclosing quotes without the extension seems to be a special case. Internal quotes without enclosing quotes don't cause a problem.
C:\test\test.bat
Code: Select all
@echo off
setlocal
echo raw: %%0 = %0
echo main: %%~tf0 = %~tf0
call :getPath
exit /b
:getPath
echo function: %%~tf0 = %~tf0
No quotes works fine:
Code: Select all
C:\test>TEST
raw: %0 = TEST
main: %~tf0 = 11/07/2013 11:05 PM C:\test\test.bat
function: %~tf0 = 11/07/2013 11:05 PM C:\test\test.bat
Enclosing quotes fails:
Code: Select all
C:\test>"TEST"
raw: %0 = "TEST"
main: %~tf0 = C:\test\TEST
function: %~tf0 = 11/07/2013 11:05 PM C:\test\test.bat
Internal quotes works fine:
Code: Select all
C:\test>T"ES"T
raw: %0 = T"ES"T
main: %~tf0 = 11/07/2013 11:05 PM C:\test\test.bat
function: %~tf0 = 11/07/2013 11:05 PM C:\test\test.bat
Enclosing quotes with full name works fine as long as working directory not changed:
Code: Select all
C:\test>"TEST.BAT"
raw: %0 = "TEST.BAT"
main: %~tf0 = 11/07/2013 11:05 PM C:\test\test.bat
function: %~tf0 = 11/07/2013 11:05 PM C:\test\test.bat
And now for some real fun
I'll combine the quote problem with the newly discovered wildcard behavior. The quoted value containing wildcards can report the wrong file if the file is added after the script has begun
C:\test\z2.bat
Code: Select all
@echo off
echo %0
echo %~f0
copy nul z1.bat >nul
echo %~f0
call :getPath
del z1.bat
exit /b
:getPath
echo %~f0
exit /b
--OUTPUT--
Code: Select all
C:\test>"Z>.bat"
"Z>.bat"
C:\test\z2.bat
C:\test\z1.bat
C:\test\z2.bat
Another obscure problem is the issue of names containing ! and/or ^ while delayed expansion is enabled.
I've written a robust
:currentScript function that should always retrieve the correct values, no matter what the circumstances. The first argument is required - the name of the variable to store the result. The second parameter is optional - a string of modifiers, without the tilde. The default modifier is F (equivalent to DPNX).
The first part of the script is a test harness for the function. It tests the function under various scenarios. I intentionally gave the script a crazy name containing characters that don't play nice with delayed expansion.
C:\test\test^it!.bat
Code: Select all
@echo off
setlocal disableDelayedExpansion
set arg0=%0
if "%arg0:~0,1%%arg0:~0,1%" equ """" (set "arg0=Quoted") else set "arg0=Unquoted"
call :header
echo %%~tzf0 = "%~tzf0"
call :currentScript rtn tzf
echo :currentScript result = "%rtn%"
setlocal enableDelayedExpansion
call :header
echo %%~tzf0 = "%~tzf0"
call :currentScript rtn tzf
echo :currentScript result = "!rtn!"
endlocal
d:
call :header
echo %%~tzf0 = "%~tzf0"
call :currentScript rtn tzf
echo :currentScript result = "%rtn%"
setlocal enableDelayedExpansion
call :header
echo %%~tzf0 = "%~tzf0"
call :currentScript rtn tzf
echo :currentScript result = "!rtn!"
exit /b
:header
set "rtn="
setlocal
echo(
echo(
if "!" equ "" (set "delayed=ON") else set "delayed=OFF"
if "%cd%\" equ "%~dp0" (set "cwd=Original") else set "cwd=Modified"
echo %arg0%: %cwd% working directory, Delayed expansion = %delayed%
echo ---------------------------------------------------------------------------
exit /b
:currentScript rtnVar [options]
setlocal
set "notDelayed=!"
setlocal disableDelayedExpansion
set "options=%~2"
if not defined options set "options=f"
call set "rtn=%%~%options%0"
if not defined notDelayed set "rtn=%rtn:^=^^%"
if not defined notDelayed set "rtn=%rtn:!=^!%"
endlocal & endlocal & set "%~1=%rtn%" !
exit /b
Here are the results using both an unquoted and a quoted call:
Code: Select all
C:\test>TEST^^IT!
Unquoted: Original working directory, Delayed expansion = OFF
---------------------------------------------------------------------------
%~tzf0 = "11/07/2013 10:43 PM 1397 C:\test\test^it!.bat"
:currentScript result = "11/07/2013 10:43 PM 1397 C:\test\test^it!.bat"
Unquoted: Original working directory, Delayed expansion = ON
---------------------------------------------------------------------------
%~tzf0 = "11/07/2013 10:43 PM 1397 C:\test\testit.bat"
:currentScript result = "11/07/2013 10:43 PM 1397 C:\test\test^it!.bat"
Unquoted: Modified working directory, Delayed expansion = OFF
---------------------------------------------------------------------------
%~tzf0 = "11/07/2013 10:43 PM 1397 C:\test\test^it!.bat"
:currentScript result = "11/07/2013 10:43 PM 1397 C:\test\test^it!.bat"
Unquoted: Modified working directory, Delayed expansion = ON
---------------------------------------------------------------------------
%~tzf0 = "11/07/2013 10:43 PM 1397 C:\test\testit.bat"
:currentScript result = "11/07/2013 10:43 PM 1397 C:\test\test^it!.bat"
C:\test>"TEST^IT!"
Quoted: Original working directory, Delayed expansion = OFF
---------------------------------------------------------------------------
%~tzf0 = "C:\test\TEST^IT!"
:currentScript result = "11/07/2013 10:43 PM 1397 C:\test\test^it!.bat"
Quoted: Original working directory, Delayed expansion = ON
---------------------------------------------------------------------------
%~tzf0 = "C:\test\TESTIT"
:currentScript result = "11/07/2013 10:43 PM 1397 C:\test\test^it!.bat"
Quoted: Modified working directory, Delayed expansion = OFF
---------------------------------------------------------------------------
%~tzf0 = "D:\TEST^IT!"
:currentScript result = "11/07/2013 10:43 PM 1397 C:\test\test^it!.bat"
Quoted: Modified working directory, Delayed expansion = ON
---------------------------------------------------------------------------
%~tzf0 = "D:\TESTIT"
:currentScript result = "11/07/2013 10:43 PM 1397 C:\test\test^it!.bat"
C:\test>
I also tested the function with batch files named
test^it.bat,
test!.bat, and
test.bat, and all worked as expected (not shown)
Dave Benham