Page 1 of 1

echo. with curious output

Posted: 31 Mar 2013 16:31
by mfm4aa
Hi, I have a curious output with the echo command in XP.
I have the following folders & files:

Code: Select all

C:\TEST
├───folder1
│       file1.iso

├───folder10
│       file10.iso

├───folder2
│       file2.iso

├───folder3
│       file3.iso

├───folder4
│       file4.iso

├───folder5
│       file5.iso

├───folder6
│       file6.iso

├───folder7
│       file7.iso

├───folder8
│       file8.iso

└───folder9
        file9.iso



and this batch code:

Code: Select all

@echo off &setlocal
for /r %%i in (*.iso) do for /f "delims=" %%j in ("%%~dpi.") do echo."%%~dpi%%~nj"
endlocal

and I got this curious output:

Code: Select all

"C:\TEST\folder1\folder1"
"C:\TEST\folder10\folder10"."C:\TEST\folder1\folder1"
"C:\TEST\folder2\folder2"."C:\TEST\folder1\folder1"
"C:\TEST\folder3\folder3"."C:\TEST\folder1\folder1"
"C:\TEST\folder4\folder4"."C:\TEST\folder1\folder1"
"C:\TEST\folder5\folder5"."C:\TEST\folder1\folder1"
"C:\TEST\folder6\folder6"."C:\TEST\folder1\folder1"
"C:\TEST\folder7\folder7"."C:\TEST\folder1\folder1"
"C:\TEST\folder8\folder8"."C:\TEST\folder1\folder1"
"C:\TEST\folder9\folder9"."C:\TEST\folder1\folder1"


and with this code:

Code: Select all

@echo off &setlocal
for /r %%i in (*.iso) do for /f "delims=" %%j in ("%%~dpi.") do echo("%%~dpi%%~nj"
endlocal

that normal output:

Code: Select all

"C:\TEST\folder1\folder1"
"C:\TEST\folder10\folder10"
"C:\TEST\folder2\folder2"
"C:\TEST\folder3\folder3"
"C:\TEST\folder4\folder4"
"C:\TEST\folder5\folder5"
"C:\TEST\folder6\folder6"
"C:\TEST\folder7\folder7"
"C:\TEST\folder8\folder8"
"C:\TEST\folder9\folder9"


Does anybody know the reason for this different behaviour (echo "." vs. "(")?

Re: echo. with curious output

Posted: 31 Mar 2013 18:39
by foxidrive

Code: Select all

@echo off
for /f "delims=" %%a in (' dir *.iso /b /s /a-d ') do echo "%%a"

Re: echo. with curious output

Posted: 31 Mar 2013 21:58
by Aacini
Your code show us another one of the (multiple) reasons to NOT use "ECHO.". You may review a more detailed explanation of this matter in this thread.

Antonio

Re: echo. with curious output

Posted: 31 Mar 2013 22:31
by foxidrive
It looks to be a bug in for /r

This works:

Code: Select all

@echo off &setlocal
for /f "delims=" %%i in (' dir *.iso /b /s ') do for /f "delims=" %%j in ("%%~dpi.") do echo."%%~dpi%%~nj"
endlocal
pause

Re: echo. with curious output

Posted: 01 Apr 2013 01:05
by jeb
Interessting effect :D

Like foxidrive said, it seems to be a bug in FOR /R.
But the bug seems to remove the line ending of the echo command.

This is enough for the bug, you need at least one subdirectory with another subdirectory.

Code: Select all

for /r %%i in ("xyz") do echo.#

Output wrote:#
#.#


But the following echo variants also fail.

Code: Select all

echo:
echo/
echo\
echo[
echo]
echo+


These one works

Code: Select all

echo(
echo=
echo;
echo,


And one appended space supresses the bug.

Code: Select all

for /r %%i in ("xyz") do echo.#<space>


After some experiments I create this one

Code: Select all

@echo OFF
setlocal EnableDelayedExpansion
set n=0
echo ON
for /r %%i in ("xyz") do set /a n+=1& echo%~1#!n!


It's the FOR-Loop expansion, which fails :!:
Output wrote:C:\temp\Sub1>for /R %i in ("xyz") do set /a n+=1 & echo.#!n!
C:\temp\Sub1>set /a n+=1 & echo.#!n!
#1
C:\temp\Sub1>set /a n+=1 & echo.#!n!.#1
#2.#1


The second expansion is very odd, the last output is appended to the new expansion :!: :?: :!:

jeb

Re: echo. with curious output

Posted: 02 Apr 2013 05:58
by dbenham
:shock: OMG, another batch stunner. :!:

The bug is not XP specific. I also see the bug on Windows 7. (No more Vista for me :D My hard drive crapped out and I replaced it and upgraded to Win 7/64)

Good sleuthing jeb :D
For anyone that couldn't figure jeb's code out, simply pass a dot as the lone argument to see the effect. Or pass any other character to test which characters work and which don't, as jeb has already done.

I simplified the code to the following

Code: Select all

@setlocal EnableDelayedExpansion
@for /r %%i in ("xyz") do echo%~1!random!

I agree the bug is with FOR /R. I wish I understood the special parsing rules of FOR better. It seems more of a parsing bug then an expansion bug to me.

The ECHO command is not directly related to the bug, though it is the only command I have found that fully expresses the problem. The VER/? command (with ECHO ON) demonstrates the bug, though it has no impact on the final output. The echoed command still manifests the bug - the /? is doubled. Since the VER output is not changed by the extra /?, I redirected output to NUL.

Code: Select all

@for /r %%i in ("xyz") do >nul ver/?
--OUTPUT--

Code: Select all

C:\test>ver/?1>nul

C:\test>ver/?/? 1>nul

C:\test>ver/?/? 1>nul

Each command within the DO clause can be affected independently. The space after the command token prevents the bug in the middle ECHO command.

Code: Select all

@setlocal EnableDelayedExpansion
@for /r %%i in ("xyz") do echo.!random!&echo.!random! &echo.!random!
--OUTPUT--

Code: Select all

C:\test>echo.!random! & echo.!random!   & echo.!random!
13706
22062
7174

C:\test>echo.!random!.13706  & echo.!random!   & echo.!random!.7174
28067.13706
15
8436.7174

C:\test>echo.!random!.13706  & echo.!random!   & echo.!random!.7174
11260.13706
7978
12414.7174

Adding parentheses and putting each command on a new line still gives the same result. It just makes the echoed command listing uglier.

Code: Select all

@setlocal EnableDelayedExpansion
@for /r %%i in ("xyz") do (
  echo.!random!x
  echo.!random! x
  echo.!random!x
)
--OUTPUT--

Code: Select all

C:\test>(
echo.!random!x
 echo.!random! x
 echo.!random!x
)
27490x
9526 x
23506x

C:\test>(
echo.!random!x.27490x
 echo.!random! x
 echo.!random!x.23506x
)
27616x.27490x
16260 x
6880x.23506x

C:\test>(
echo.!random!x.27490x
 echo.!random! x
 echo.!random!x.23506x
)
8415x.27490x
13789 x
29795x.23506x


Dave Benham

Re: echo. with curious output

Posted: 02 Apr 2013 16:56
by jeb
Hi Dave,

dbenham wrote: It seems more of a parsing bug then an expansion bug to me.

Yes you are right, it seems to be a parsing issue :!:

It seems only be visible when only a command token exists, but no other token in the line.

No bugs here

Code: Select all

for /r %%i in ("xyz") do (
   echo Hello
   set/a.x,b=60
)


But now, both lines have the bug.

Code: Select all

set a.x=2
for /r %%i in ("xyz") do (
   echo^ Hello
   set/a.x^,b^=60
)


The set command can also be affected, but it's tricky to create a working construct :)

jeb

Re: echo. with curious output

Posted: 08 Apr 2013 02:01
by jeb
:) I'm played a bit with double delayed expansion and I found another curious effect.

The idea behind the double delayed expansion is to get a similiar expression to the CALL percent expansion like
call set var=%%text:~%idx%%%


Now the code for double delayed expansion

Code: Select all

@echo off
SetLocal EnableExtensions EnableDelayedExpansion
cd "Sub1"
set n=2
set y=abcdefg
set var=empty
@echo on
for /r %%i in ("xyz") do (
   echo^ "var=^!y:~!n!^!
   set^ "var=^!y:~!n!^!
)
@echo off
set var


Output wrote:C:\temp\Sub1>for /R %i in ("xyz") do (
echo "var=^!y:~!n!^!
set "var=^!y:~!n!^!
)

C:\temp\Sub1>(
echo "var=^!y:~!n!^!
set "var=^!y:~!n!^!
)
"var=!y:~2!

C:\temp\Sub1>(
echo "var=^!y:~!n!^! "var=!y:~2!
set "var=^!y:~!n!^! "var
)
"var=!y:~2! "var=cdefg
var=!y:~2!


The interessting part is the last expansion :!:
echo "var=^!y:~!n!^! "var=!y:~2!
set "var=^!y:~!n!^! "var


I can't see the reason, why it expands different for echo^ and set^ :?:

jeb

Re: echo. with curious output

Posted: 08 Apr 2013 04:46
by jeb
foxidrive wrote:I'm not sure what you have in the sub1 folder.

Ok, I forgot to said: In the Sub1 folder is a Sub2 folder, which itself is empty.

That is required to see the FOR/R-bug

jeb

Re: echo. with curious output

Posted: 14 Apr 2013 21:54
by dbenham
jeb wrote:I can't see the reason, why it expands different for echo^ and set^ :?:
That pesky = must have special significance to the FOR parser when dealing with the SET command.

I can manage to get your double delayed expansion to work with the SET command. Interesting, but not very practical.
I also managed to create a more interesting example for SET /A.

Code: Select all

@echo off
SetLocal EnableExtensions EnableDelayedExpansion
cls
set a=2
set y=abcdefg
echo on&for /r %%i in (xyz) do (
  echo^ test_^^!y:~!a!^^!^=
   set^ test_^^!y:~!a!^^!^=
   set/a^ b^=60
)
@echo off
echo -----------------------------------
set test_
echo b=%b%
--OUTPUT--

Code: Select all

C:\test>(
echo test_^!y:~!a!^!=
 set test_^!y:~!a!^!=
 set/a b=60
)
test_!y:~2!=

C:\test>(
echo test_^!y:~!a!^!= test_!y:~2!=
 set test_^!y:~!a!^!= test_!y:~2!
 set/a b=60/a b=60
)
test_!y:~2!= test_cdefg=
Missing operator.
-----------------------------------
test_!y:~2!= test_cdefg
b=30


Dave Benham