Page 1 of 3

ECHO. FAILS to give text or blank line - Instead use ECHO/

Posted: 09 Dec 2009 11:19
by alan_b
The following tip is unreliable :-
http://www.dostips.com/DtCodeSnippets.p ... oEmptyLine

Also you may fail to get blank space BEFORE text from "ECHO. text"

Instead of an empty line, or " text", it may instead announce
'echo.' is not recognized as an internal or external command,
operable program or batch file.

The above error happens if the CMD.EXE can find an extension-less file with the name echo, in which case instead of "echoing" text it tries to execute that file, even if that file has zero length.

Various alternatives seem to work more reliably, including
ECHO\
ECHO:
ECHO/

Because I wasted a few hours of my life debugging a very complex batch script to identify this problem, I prefer to avoid any future confusion of : and \ as elements of a file path, and am now using
ECHO/

Alan

Posted: 10 Dec 2009 12:35
by avery_larry
Seems quite logical that a file which is named the same thing as a reserved command would cause problems.

Posted: 10 Dec 2009 16:22
by alan_b
I agree that a file called "echo" MAY cause problems,
but feel it is inappropriate for DosTips to needlessly punish an innocent user of a batch script that happens to visit a multiplicity of folders to purge junk that was left behind when a security program was removed.

After installing Comodo Firewall I ran a user forum supplied script to remove many remnants that were typically left behind, BUT due to permissions issues I spotted the odd "Access is denied" and "cannot access" within the screens of output messages as CD and DEL and REG.EXE commands flooded my monitor, but no clue upon which command / target was responsible. The script aimed CD at a directory that was often not present, but ignored the error and proceeded to delete any files with "target" names that happened to be in its previous CD location. It also ignored "Access is denied" and "cannot access" messages. I inserted ECHO ON in various places to track down the command / targets giving problems, and then I took ownership and resolved the permissions problems. The original script ignored all errors, and a few VITAL "access" errors were totally obscured by the flood of so many perfectly VALID "error" messages, e.g. :-
The system cannot find the path specified.
Could Not Find ...
Error: The system was unable to find the specified registry key or value.

I ran that user script 12 times in 25 minutes whilst identifying and fixing permission issues. When I finally succeeded with a sigh of relief I rebooted and then checked the event log for errors.

There was some problem with recovery on 4 off .NET framework files upon the first reboot, but further reboots appeared error free.
I subsequently found that ...\System32\wbem\AutoRecover had increased from the 10 off *.MOF files accumulated during the 5 year life of the P.C. to 54 files. I am concerned that in 25 minutes that script with no error checking has now added another 22 years worth of degradation to my P.C. - and .NET Framework was bad enough before all this ! ! !

I now believe that the original script corrupted Catroot which has now been rebuilt, BUT AutoRecovery still holds 54 *.MOF files and I have asked on 6 forums but no-one has given definitive guidance upon whether the corruption has been cured or masked.

I have decided to restore the drive C:\ image I captured BEFORE I removed Comodo, and avoid all errors as I make a second attempt.

For my second attempt I have revised the original script with all output and error messages redirected to error checking that suppresses all "not present" types of indications, and only displays the "permission failure" types of errors.

I was disappointed that my final test run of my script included the spurious
"'echo.' is not recognized as an internal or external command,
operable program or batch file."

This error was only when deleting files from one specific directory that happened to have a file named "ECHO". This error was produced by only one of a large number of "ECHO." command with which I was documenting the progress of the script. This error only happened upon the first run of the script within a DOS shell - subsequent runs had no such error. I only saw an error because of my extreme care.
It took me a few hours to identify and cure the problem.

To avoid any future problems I will never again use "ECHO." for a blank line.
I suggest it would be a kindness to forum members if the unreliable "ECHO." be replaced with anything else (such as ECHO/) to avoid punishing them for the presence of a naughty ECHO file that they never knew about.

Technically, ECHO. is a serious waste of CPU cycles.

My experience demonstrates that when file ECHO exists in the current directory the script will try to execute that file. This implies that if the file ECHO exists ANYWHERE on the %PATH% it will be executed.
WORSE, even if there is no such file, when the script encounters "ECHO." it will not immediately print the blank line, but will first trawl through every directory that is on the %PATH% to see if there is an ECHO to execute.

For the last 30 years I have designed Real Time security systems with 8 bit processors. My focus has been to ensure continuous unstoppable error free operation, and efficiency of code in a limited address space. I ensured the code was correct, and that it had dependable fail-safe mechanisms for dealing with the unexpected.

Windows has been a bitter pill to swallow now that I am retired.

The presence of a file named "ECHO" was unexpected, but should now be no surprise, and I feel that once an unexpected error mechanism has been identified it should be avoided.

Regards
Alan

Posted: 11 Dec 2009 00:01
by DosItHelp
alan_b,

Your finding is quite interesting. I reproduced the issue on a XP box. The problem only seems to happen when a file named "echo" exist in the current directory. I could not see the problem if the file exist in a different directory referenced by the path variable.
To try this out I create a file named "echo" in the c:\windows\system32 folder, which is referenced in the path variable, and then run "echo. ecko#" inside and outside this folder from a command line. Here is a dump:

Code: Select all

C:\>echo. ekko1&pushd c:\windows\system32&echo. ekko2&popd
 ekko1
 ekko2

C:\>type NUL>c:\windows\system32\echo

C:\>echo. ekko1&pushd c:\windows\system32&echo. ekko2&popd
 ekko1
'echo.' is not recognized as an internal or external command,
operable program or batch file.

C:\>del c:\windows\system32\echo

C:\>echo. ekko1&pushd c:\windows\system32&echo. ekko2&popd
 ekko1
 ekko2

Then I run it from a batch file, with same result:
C:\>copy con a.cmd
@echo off
echo. ekko1&pushd c:\windows\system32&echo. ekko2&popd
type NUL>c:\windows\system32\echo
echo. ekko1&pushd c:\windows\system32&echo. ekko2&popd
del c:\windows\system32\echo
echo. ekko1&pushd c:\windows\system32&echo. ekko2&popd
^Z
1 file(s) copied.

C:\>a.cmd
ekko1
ekko2
ekko1
'echo.' is not recognized as an internal or external command,
operable program or batch file.
ekko1
ekko2

This suggest the following search order for executable commands:
1. current directory
2. internal commands
3. directories referenced in the path variable

Alternatives:
Echo\ - seems to be unacceptable as well since someone could try "echo\hello world" while having a directory named "echo" with file named "hello" in it.

Code: Select all

C:\>echo\Hello World
Hello World

C:\>md echo&type NUL>echo\hello

C:\>echo\Hello World
'echo\Hello' is not recognized as an internal or external command,
operable program or batch file.

C:\>del echo\hello&rd echo

C:\>echo\Hello World
Hello World

So there could be hidden traps in other options as well.
I found these options appear to work but which one is best and why?

Code: Select all

C:\>echo.


C:\>echo/


C:\>echo\


C:\>echo:


C:\>echo+


C:\>echo=


C:\>echo;


C:\>echo,

If we find a reliable option then I would adapt this to all dostips pages, but I would want to be sure.
Thanks a lot for your input. I'll get back on this.

Posted: 11 Dec 2009 06:40
by alan_b
Thank you for your response.

ECHO+ is not safe.

Contents of ECHO_DOT.BAT

Code: Select all

@echo off
ECHO  About to issue command ECHO+ A B C D E F
ECHO+ A B C D E F
ECHO  Have now issued command ECHO+ A B C D E F
PAUSE

NORMAL consequence of ECHO_DOT.BAT
About to issue command ECHO+ A B C D E F
A B C D E F
Have now issued command ECHO+ A B C D E F
Press any key to continue . . .

Contents of ECHO+.BAT

Code: Select all

echo this is "%~f0",
ECHO arguments %0 %*
pause

SPECIAL consequence "A" of ECHO_DOT.BAT when ECHO+.BAT is on %PATH%
About to issue command ECHO+ A B C D E F
this is "C:\Program Files\QuickTime\QTSystem\echo+.bat",
arguments ECHO+ A B C D E F
Press any key to continue . . .

SPECIAL consequence "B" of ECHO_DOT.BAT when ECHO+.BAT is in current directory
About to issue command ECHO+ A B C D E F
this is "D:\#\Comodo_Update\echo+.bat",
arguments ECHO+ A B C D E F
Press any key to continue . . .


I suggest that if a character is acceptable to Windows as being part of a file name, then that character cannot be safely used as a "suffix" to ECHO, otherwise CMD.EXE will trawl through the current directory and then the %PATH% trying to find "ECHO+" with an executable extension.
(I have not tested this for all possibilities, but I am fairly confident of my theory.)

Regards
Alan

Re: ECHO. FAILS to give text or blank line - Instead use ECH

Posted: 10 Aug 2010 12:20
by jeb
alan_b wrote:I suggest that if a character is acceptable to Windows as being part of a file name, then that character cannot be safely used as a "suffix" to ECHO, otherwise CMD.EXE will trawl through the current directory and then the %PATH% trying to find "ECHO+" with an executable extension.
(I have not tested this for all possibilities, but I am fairly confident of my theory.)


I tested it today.
With cmd /? you got the list of characters that can be used in a filename, but requires quotes for the filename

Code: Select all

<space>
()[]{}^=;!'+,`~


But only ",;=(:" seems to work
".[]{}+)^!'`~" don't work, incomprehensible why "(" work, but not ")" :?:

I can't believe that "echo(" is always working.
But ":" could be a good solution, because it is not allowed in a filename

Re: ECHO. FAILS to give text or blank line - Instead use ECH

Posted: 12 Aug 2010 11:25
by alan_b
Jeb

When I saw your post I accepted that it appeared to be an equally valid solution to my use of /
But I saw no reason to change what I was using.

Today I hit disaster.
It turns out that the usage of a command is displayed by appending /?
(which we all knew)
but it is also displayed by those same two characters regardless of the presence or absence of white space.

The command
ECHO/ ? WHAT'S UP DOC ?
gives a result I never expected ! !

I remembered your post as if it was yesterday, and the job is done correctly by
ECHO: ? WHAT'S UP DOC ?

I have returned to say your solution is better than mine,
but after reviewing the whole topic have an anxiety and recommend your alternative suggestion of the semi-colon.

I started this topic last year, and found I could use any of the 3 characters \:/
and because of a sad experience (which is now beyond the event horizon for my memory) with a file path, I decided that \ and : could trip me up, so I chose /

I do not know if : is guilty, I just remember burnt fingers !

I agree that it is strange that ")" does not work but "(" is O.K.
If in theory both "(" and ")" are equally usable,
but in practise ")" does not work for some unknown reason when tested,
I have a fear that "(" will fail for the same or similar reason when tested a lot more.

I am now using the semi-colon and hope that will always be good for me.

I also have an emotional fondness for the semi-colon.
It was the first character of a line of assembler to denote this line is comment and not code.
It reminds me of the happy days when I first programmed a computer using assembler,
and the computer always did exactly what I told it to do and when I told it.
Oh for the good old days before Windows and BSODs !

Regards and thanks
Alan

Re: ECHO. FAILS to give text or blank line - Instead use ECH

Posted: 12 Aug 2010 12:17
by jeb
Ok, i tested it again, and this are my results

These one fails always (command can not be found)

Code: Select all

echo{
echo}
echo)
echo^
echo!
echo'
echo`
echo~
EDIT: I fixed some incorrect description, see also Discussion about jeb's batch parsing rules on StackOverflow
These one fails, if files exists like echo*.bat, the * is one of "[]+"

Code: Select all

echo[
echo]
echo+
This, often used, but it will call "echo.bat" if the file exists.
If only a file named "echo" (without extension) exists, then it failed completly with an error message

Code: Select all

echo.
These one fails, if a file in the current directory exists named my.bat

Code: Select all

echo\..\my.bat
echo:\..\my.bat
echo.\..\my.bat
These one fails independet of a file, they show the HELP of the ECHO command

Code: Select all

echo/?
echo,/?
echo;/?
echo=/?
Ok, now we have a problem, there is only one usable character left. :?
The "(", which I agree with you, that this presumably has other side effects.

hope it helps
jeb

Re: ECHO. FAILS to give text or blank line - Instead use ECH

Posted: 12 Aug 2010 14:35
by alan_b
You got me again ! !

Thanks, I will now be using the "("

I have the beginnings of a theory that might explain failure of the ")"

Blocks of code may be contained within brackets for things like
IF EXIST FILE (ECHO FOUND IT) ELSE (ECHO LOST IT)
Perhaps cmd.exe knows that something may follow an opening (
and suspends judgement to see what comes next.
Perhaps it that ) is the "end of an era" and therefore to maintain balance there has to be a previous (,
and when I do not work within its expectations, it retaliates with a surprise.

Not a convincing theory,
but it helps me to sleep at night if I think I understand the world ! !

Regards
Alan

Re: ECHO. FAILS to give text or blank line - Instead use ECH

Posted: 18 Jan 2011 07:42
by amel27
Hi All!
some more constraint of "ECHO." with explanation in DelayedExpansion mode:

Code: Select all

echo !str:~-2!
echo.!str:~-2!
echo:!str:~-2!
echo.
echo !str:0=9!
echo.!str:0=9!
echo:!str:0=9!
echo.
echo !str:~0,-2!
echo.!str:~0,-2!
echo:!str:~0,-2!
result:

Code: Select all

90
90
90

1234567899
str:0=9
str:0=9

12345678
str:~0,-2
str:~0,-2

...any suggestions?

Re: ECHO. FAILS to give text or blank line - Instead use ECH

Posted: 18 Jan 2011 16:45
by jeb
Hi amel27,

an interessting effect, I never thought about.

But the cause is obvious :D

It's the standard tokenizer in phase 2 (the special character phase of the BatchLineParser).
The tokenizer splits the tokens in phase2 and use as delims <space>,;= and sometimes also <ALT-255>
So the first token in your "good" case is
cmd="echo:!str:~2!"
The command token will be expanded later

But in the case of

Code: Select all

echo:!str:0=9!
the token is evaluated to

Code: Select all

cmd="echo:!str:0" 


The evaluation of the command is after the expansion, but the ":" split the "echo" from the "!str:0" so it will be executed as a normal "echo".

But why the complete !str:0=9! is visible?
Because the echo command doesn't use the tokens, it access the "raw" line.

Btw.

Code: Select all

echo(!str:0=9!

works, because the tokenizer detects only the "echo" as the cmd

hope it helps
jeb

Re: ECHO. FAILS to give text or blank line - Instead use ECH

Posted: 19 Jan 2011 03:03
by amel27
Thanks jeb, it is helpful
...but "ECHO(" not compatibly with parentheses

Code: Select all

(
echo(!str:0=)!
)

...and some more constraints added: :roll:

Code: Select all

@echo off
SETLOCAL EnableDelayedExpansion

set str=FFFF00000

echo.
echo str:%str%
echo sub:^^!str:0=F^^!

echo.
echo sometimes tokens delims not restored
for /f "delims=" %%a in ('echo !str:0=F!') do echo %%a

echo.
echo but we can fix this with dblquotes
for /f "delims=" %%a in ('"echo !str:0=F!"') do echo %%a

echo.
echo ...but how tokenizer work with ECHO. now?
for /f "delims=" %%a in ('"echo.!str:0=F!"') do echo %%a

pause>nul

Re: ECHO. FAILS to give text or blank line - Instead use ECH

Posted: 19 Jan 2011 21:10
by jeb
Many thanks amel27,
I found a new behavior, but first ...

amel27 wrote:...but "ECHO(" not compatibly with parentheses

(
echo(!str:0=)!
)
Not the "echo(" is the problem, it fails because of the ")" in !str:0=)!


amel27 wrote:...and some more constraints added:
echo ...but how tokenizer work with ECHO. now?
for /f "delims=" %%a in ('"echo.!str:0=F!"') do echo %%a
The "echo." doesn't see the "!str:0=F!", because the expansion of the delayed expression is just before the FOR-Loop starts the "echo." in a new cmd.exe.


amel27 wrote:echo sometimes tokens delims not restored
for /f "delims=" %%a in ('echo !str:0=F!') do echo %%a
But that is the normal effect of the for loop, it does not depends on delayed expansion

Code: Select all

for /f "delims=" %%a in ('echo a,b=c;d==;;,,e') do echo %%a
--- Output ----
a b c d e



But your ideas shows me a new behaviour of the delayed expansion. :o

Code: Select all

SETLOCAL EnableDelayedExpansion
echo ^^^^--"^^" 1 "^^" ^^^^
echo ^^^^--"^^"   2 "^^" ^^^^ !
echo !^^^^--"^^"   3 "^^" ^^^^
echo:!^^^^--"^^"   4 "^^" ^^^^ WOW

--- OUTPUT ----
^^--"^^" 1 "^^" ^^
^--"^"   2 "^" ^
^--"^"   3 "^" ^
^--"^"   4 "^^" ^^ WOW


Line 1 - the expected result, the caret escapes outside of quotes the next character
Line 2 and 3 - first like 1, but as there is a "!" present, the carets escapes the next character a second time, now also in quotes
Line 4 is impressive
It shows that the command-token and the rest of the line are handled separately.
The first part is handled through the delayed phase but not the second part.

jeb
jeb

Re: ECHO. FAILS to give text or blank line - Instead use ECH

Posted: 20 Jan 2011 04:54
by amel27
jeb wrote:It shows that the command-token and the rest of the line are handled separately.
Great! Most likely, that delayed expansion work after tokens merged to "supertokens" like command or text stream (list of parameters), and each "supertoken" expand separately…

jeb wrote:Not the "echo(" is the problem, it fails because of the ")" in !str:0=)!
Yes, the problem is in separate "(" char before, that toggle the block flag. "(" not detected as trigger in the middle or at the end of word, where it is equivalent of ordinary letter. Each another "(" trigger increment block counter. If the block flag is active, interpreter find ")" in each char as block end (quote (") mute this effect), and if found - select block and decrement counter. If counter=0, block flag is disable and ")" char is equivalent of ordinary letter.

Code: Select all

 @echo off
SETLOCAL EnableDelayedExpansion

set username)
(
set username)
set username)

--- OUTPUT ----
 Environment variable username) not defined
USERNAME=MyName
Environment variable username) not defined


jeb wrote:
amel27 wrote:but how tokenizer work with ECHO. now?
for /f "delims=" %%a in ('"echo.!str:0=F!"') do echo %%a
The "echo." doesn't see the "!str:0=F!", because the expansion of the delayed expression is just before the FOR-Loop starts the "echo." in a new cmd.exe.
delayed expression start twice - but each of them BEFORE run new cmd.exe:

Code: Select all

 @echo off
set "var=F0!var!"

SETLOCAL EnableDelayedExpansion
echo 1:
for /f "delims=" %%a in ('"set var=& echo:!var!"') do echo %%a
echo 2:
for /f "delims=" %%a in ('"echo:!var:0=F!& echo:^^^!var:0=F^^^!"') do echo %%a

--- OUTPUT ----
1:
F0F0!var!
2:
FFF0!var!
FF!var!

Re: ECHO. FAILS to give text or blank line - Instead use ECH

Posted: 20 Jan 2011 06:10
by jeb
delayed expression start twice - but each of them BEFORE run new cmd.exe:


No it starts only once, the second delay is in the echo %%a itself.

Code: Select all

@echo off
set "var=F0!var!"

SETLOCAL EnableDelayedExpansion
echo 1:
for /f "delims=" %%a in ('"set var=& echo:!var!"') do (
  echo 1 delayed %%a
  SETLOCAL DisableDelayedExpansion
  echo 1 undelay %%a
  endlocal
)
echo 2:
for /f "delims=" %%a in ('"echo:!var:0=F!& echo:^^^!var:0=F^^^!"') do (
   echo 2 delayed %%a
   SETLOCAL DisableDelayedExpansion
   echo 2 undelay %%a
   endlocal
)