Discussion:
echo a variable containing an & sometimes works, sometimes not. Why ?
(too old to reply)
R.Wieser
2022-11-20 11:48:12 UTC
Permalink
Hello all,

I've written a test batch showing a directory tree. In it I noticed that
echo-ing an argument containing a pathname containing an "&" causes a
problem when done directly :

echo %~xn1

but doesn't when done indirectly :

for %%a in (%1) do echo %%~xna

Does anyone have an explanation for it ?


And a question : How do I tell the batchfile parser *not* to parse the %~xn1
results but instead just display it as-is ?

I know that I can wrap it in doublequotes :

echo "%~xn1"

but those doublequotes get displayed too. :-(

Regards,
Rudy Wieser
Kerr-Mudd, John
2022-11-20 13:08:13 UTC
Permalink
On Sun, 20 Nov 2022 12:48:12 +0100
Post by R.Wieser
Hello all,
I've written a test batch showing a directory tree. In it I noticed that
echo-ing an argument containing a pathname containing an "&" causes a
echo %~xn1
'&' is seen as a command concatenation symbol; e.g.
echo Missed it!&cls
Post by R.Wieser
for %%a in (%1) do echo %%~xna
Does anyone have an explanation for it ?
DelayedExpansion set?
Post by R.Wieser
And a question : How do I tell the batchfile parser *not* to parse the %~xn1
results but instead just display it as-is ?
Ah so you kind of knew why!
Post by R.Wieser
echo "%~xn1"
but those doublequotes get displayed too. :-(
Don't make directory names with '&' in them?
(Sorry, not very helpfull)
--
Bah, and indeed Humbug.
R.Wieser
2022-11-20 14:18:11 UTC
Permalink
John,
Post by Kerr-Mudd, John
'&' is seen as a command concatenation symbol; e.g.
echo Missed it!&cls
Thank you, but I was aware of that. :-) To be honest, I'm thinking a bit
further and am using that "&" as a placeholder for other special-meaning
characters.
Post by Kerr-Mudd, John
DelayedExpansion set?
Nope, but thanks for the suggestion. Alas, I just tried to put it at
several different locations but still got the same result.
Post by Kerr-Mudd, John
Ah so you kind of knew why!
:-) As someone who was lucky enough to have been provided with a
functioning brain I can observe and deduce.
Post by Kerr-Mudd, John
Don't make directory names with '&' in them?
(Sorry, not very helpfull)
:-p Yeah, that was one of my own thoughts too. Although that could work
for my own drives, all bets are off when I would dare to use it on someone
elses USB stick or similar.

Regards,
Rudy Wieser
JJ
2022-11-20 13:39:23 UTC
Permalink
Post by R.Wieser
Hello all,
I've written a test batch showing a directory tree. In it I noticed that
echo-ing an argument containing a pathname containing an "&" causes a
echo %~xn1
for %%a in (%1) do echo %%~xna
Does anyone have an explanation for it ?
FOR's variables are not parsed. AFAIK, FOR variables are expanded *after*
the command line has been parsed. Non-DelayedExpansion normal variables in
the command line are expanded *before* the command line is parsed.
Post by R.Wieser
And a question : How do I tell the batchfile parser *not* to parse the %~xn1
results but instead just display it as-is ?
echo "%~xn1"
but those doublequotes get displayed too. :-(
DelayedExpansion can be used, but escape character may need to be specified
twice when it's needed. Adding complexity for normal variables usage. It may
cause a problem which is unsolvable instead.

For non-DelayedExpansion normal variables, we'd have to use FOR variable to
display it. e.g.

@echo off
setlocal
set s=abc ^& def

echo this causes error
echo %s%

echo.
echo this won't cause error
for %%A in ("%s%") do echo %%~A
R.Wieser
2022-11-20 14:35:10 UTC
Permalink
JJ,
AFAIK, FOR variables are expanded *after* the command line
has been parsed. ... normal variables in the command line
are expanded *before* the command line is parsed.
That was my conclusion too. But I see that my question was imprecise. The
"why" was aimed more at "why does it happen in two different ways".

Though I just now remembered having recently read that the batch scripting
language has evolved over time, and with evolution lots of weird things can
happen.
DelayedExpansion can be used, but escape character may need
to be specified twice when it's needed. Adding complexity for
normal variables usage. It may cause a problem which is unsolvable
instead.
Argh!
For non-DelayedExpansion normal variables, we'd have to use FOR
variable to display it. e.g.
:-) Yep, as I included in my initial post (the "but doesn't when done
indirectly" example).

Regards,
Rudy Wieser
Herbert Kleebauer
2022-11-20 18:54:56 UTC
Permalink
Post by R.Wieser
Hello all,
echo "%~xn1"
but those doublequotes get displayed too. :-(
I don't know how to get a & in %1 without surrounding it
in "" so I can't test it. But set/p seems to remove the "":

@echo off

call :sub "d:\a&b\c\te&st.123"
goto :eof

:sub
echo %1
set /p a="%~xn1"<nul
echo.
R.Wieser
2022-11-20 20:04:33 UTC
Permalink
Herbert,
Post by Herbert Kleebauer
set /p a="%~xn1"<nul
...
Post by Herbert Kleebauer
I don't know how to get a & in %1 without surrounding it
in "" so I can't test it.
Ive put a few lines of text ("hello&world", "&foo", "bar&") in a file,
retrieved those lines and than called your ":sub" with it like this :

for /f %%i in (words.txt) do call :sub %%i

, but for some reason your ":sub" was not called for the first two (though
no error or other output), but it was for the third/last line. IOW, I could
not test it either ...

It "ofcourse" worked fine when I enclosed the %%i argument in double-quotes,
but that also negated the test itself. :-|
It does seem to do that, yes. Though I think I like the

for %%a in (%1) do echo %%~nxa

trick better. :-)

I also tried a line (in the textfile) with an embedded doublequote. The it
caused the "set /p" to wait for input again. And ofcourse the simple "echo
%1" had no problems with it.

Regards,
Rudy Wieser
JJ
2022-11-21 00:51:28 UTC
Permalink
Post by R.Wieser
Ive put a few lines of text ("hello&world", "&foo", "bar&") in a file,
for /f %%i in (words.txt) do call :sub %%i
, but for some reason your ":sub" was not called for the first two (though
no error or other output), but it was for the third/last line. IOW, I could
not test it either ...
CALL would force the command line to be parsed and expanded twice.

On the second command line processing, the `%%i` is already expanded, so it
is or should be treated as a command separator. However, it seems that
there's a bug on the second command line processing, since it may cancel the
CALL command execution. Below is a simple demo of this bug.

@echo off
setlocal
set a=hello^&world
set b=%%a%%

rem output: abc "hello&world"
call echo abc "%b%"

rem expected output: hello&world
rem but since `%b%` is not quoted, after expansion,
rem the `&` should be treated as a command reparator.
rem but it cancels the whole command line.
call echo abc %b%

echo end
Post by R.Wieser
I also tried a line (in the textfile) with an embedded doublequote. The it
caused the "set /p" to wait for input again. And ofcourse the simple "echo
%1" had no problems with it.
Chances are that, your SET /P is like this.

set /p a="%1"<nul

Since the paramater is already quoted, the parsed command line would be like
below, where the quotes from SET /P are paired with the ones from the
contents of `%1`. Making the `hello&world` unquoted, and the `&` character
be treated as command separator.

So the quotes from the content of `%1` should be stripped first. i.e.

set /p a="%~1"<nul
R.Wieser
2022-11-21 06:42:45 UTC
Permalink
JJ,
However, it seems that there's a bug on the second command
line processing, since it may cancel the CALL command execution.
...
rem but since `%b%` is not quoted, after expansion,
rem the `&` should be treated as a command reparator.
which is why I expected /something/ to be displayed, even just that the word
after the "&" could not be found as a command.

Thanks for the confirmation of the problem/bug.
Chances are that, your SET /P is like this.
set /p a="%1"<nul
...
So the quotes from the content of `%1` should be stripped first. i.e.
set /p a="%~1"<nul
That is what herbert offered me, I used and the problem happened with :

set /p a="%~xn1"<nul

Minimal example :
- - - - - - - - - - - - - - -
call :sub hello^"world
goto :eof
:sub
set /p a="%~1"<nul
goto :eof
- - - - - - - - - - - - - - -
Strange though, the string 'hello"world' gets displayed (IOW: with its
embedded doublequote). No idea how it can cause the following "<nul" to be
ignored.

Brainfart: I just remembered that there is no rule that the redirection has
to be done at the end. To get rid of /this/ problem tried putting it at the
start, and the problem was gone.

<nul set /p a="%~1"

IOW, it /is/ a parsing problem, but I've got no idea how.


Just to check I've also tested putting it somewhere in the middle, and all
of the below three work as well. A nice way to throw someone in a spin.
:-)

set <nul /p a="%~1"
set /p <nul a="%~1"
set /p a<nul="%~1"

Regards,
Rudy Wieser
JJ
2022-11-21 11:16:57 UTC
Permalink
Post by R.Wieser
Just to check I've also tested putting it somewhere in the middle, and all
of the below three work as well. A nice way to throw someone in a spin.
:-)
set <nul /p a="%~1"
set /p <nul a="%~1"
set /p a<nul="%~1"
I need someone's head so I could pull his hairs out.

Loading...