The issue is that the call
command parses the command line call:test "%%d"
(which should read call :test "%%~d"
) a second time:
- At first,
%%d
becomes expanded to the currently iterated file, which is %~aaa.txt
in the failing situation.
- The expression
%~aaa.txt
now becomes parsed another time due to the call
command, where %~
is the beginning of an argument reference, the following a
is a modifier (~a
would expand to file attributes), but there is the decimal digit missing (%~a1
or %~aaa2
were valid, for instance).
To work around that, you could put the argument into a normal environment variable and read it in the sub-routine (I used delayed variable expansion therein in order to avoid troubles with special characters):
for %%d in (*.txt) do (
set "ARG=%%~d"
call :test
)
exit /B
:test
setlocal EnableDelayedExpansion
echo(!ARG!
endlocal
exit /B
You could also pass the variable name as an argument to the sub-routine:
for %%d in (*.txt) do (
set "ARG=%%~d"
call :test ARG
)
exit /B
:test
setlocal EnableDelayedExpansion
echo(!%~1!
endlocal
exit /B
Another way is to let call
expand the actual file name during its second parsing phase:
for %%d in (*.txt) do (
set "ARG=%%~d"
call :test "%%ARG%%"
)
exit /B
:test
set "STR=%~1"
setlocal EnableDelayedExpansion
echo(!STR!
endlocal
exit /B
To avoid issues with file names containing ^
, &
or other special characters, a simple echo(%~1
in the sub-routine is avoided.