Why does attempting to echo an undefined environment variable result in the message “ECHO is on”?


From a batch file, suppose you try to echo the contents of a variable that hasn't been defined:

set AWESOME=1
echo %AWESUM%

This prints ECHO is off. What's up with that?

The first half of the puzzle is knowing that if a variable is not defined, then it expands to an empty string. Therefore, after expension, the command

echo %AWESUM%

becomes simply

echo

The second half of the puzzle is knowing that the ECHO command, if run with no command line, reports the current echo state, printing either ECHO is on or ECHO is off, accordingly.

Putting it all together: If you try to echo the value of an undefined variable, and the variable is not defined, then the echo command gets a blank command line, at which point it reports its current state.

So how do you echo the value of a variable that might be undefined?

One way is to put something else on the command line.

echo AWESUM=%AWESUM%

If AWESUM is not defined, this will expand to

echo AWESUM=

and that prints AWESUM=.

Okay, but what if you really want to echo the value on a line all by itself?

You can exploit a quirk of the ECHO command: If you follow the word ECHO immediately with a period (no space), then the period is not echoed, but the presence of the period suppresses the "no command line" behavior, and you get a blank line.

ECHO.

That prints a blank line.

If you want to print a variable that might not be defined, you would say

ECHO.%AWESUM%

This quirk of the ECHO command was originally a bug in the command line parser, but once people discovered it, the bug became elevated to a feature. (The phenomenon of a bug elevated to a feature happens a lot. Obligatory XKCD.)

Exercise: Explain the output of this batch file, and how would you fix it so it prints /??

set message=/?
echo %message%
Comments (25)
  1. pc says:

    As the echo documentation says (when you run “echo /?”):

    Displays messages, or turns command-echoing on or off.

    ECHO [ON | OFF]
    ECHO [message]

    Type ECHO without parameters to display the current echo setting.

    That is to say, that “echo” does two completely unrelated things. Many arguments are “special”, including “on”, “off”, “/?”, and “”. Any argument that isn’t “special” gets output.

    It looks like “echo.%message%” works in my very limited testing.

    1. Antonio Rodríguez says:

      Right. As stated by Raymond, the dot precludes echo from looking for modifiers in the argument list. Also, this is a bug turned into a feature, so I think you can rely on it working in the future.

  2. James Curran says:

    actually, I think

    set message=ON
    echo %message%

    might be a bit more confusing to the user. Same solution though..

    echo.%message%

  3. David Trapp says:

    Why is it that when entering the commands interactively, undefined environment variables just don’t expand at all?

    For example:

    Z:\>echo %username% %foobar% %cd%
    david %foobar% Z:\

    1. You also have to double the percent signs in the for variable when in a batch file, but not when on the command line. Batch is weird.

  4. anonymous says:

    When I try this it echos %AWESUM%

    1. You get different behavior on the command line as opposed to in a batch file.

  5. batcher says:

    Why do batch file labels crossing a 512-byte boundary still not work? Are there really batch files out there which depend on that quirk?

    1. They seem to work for me. I wrote a batch file that said “goto label” then “rem xxxxxxxxxx” with enough x’s to pad to 508 bytes. Then “:label” and “echo arrived”, and the “goto” successfully found the label.

      1. batcher says:

        Sorry, I forgot to write that this only happens if lines are terminated with LF rather than CRLF.

        1. Batch files must use CRLF. Otherwise the behavior is undefined.

  6. JJJ says:

    The batch file gurus over at dostips (some also active on stackoverflow) don’t use “echo.” because it fails when there is a file named “echo” in the same directory. There are also other failure cases if you use it with delayed expansion variables on the line. They discovered that the most robust character is ‘(‘, so you’ll see them writing “echo(” in their scripts.

    Source: http://www.dostips.com/forum/viewtopic.php?p=4554#p4554

    For some reason, I love batch files. Maybe it’s because every task, no matter how easy in other languages, is a complex puzzle to solve in batch. (For example, string length.)

  7. Queue says:

    For… decades maybe, I’ve been using echo; instead of echo.
    I’m positive that it works for both command.com and cmd.exe since I have at least one massive complex batch file that is still run under both Win98SE and Win7 regularly.
    If memory serves, it had something to do with file i/o, that echo. hit the file system before falling back to treating the period as a delimiter while echo; didn’t. Or something; it’s been a while since I ran a bunch of batch variations through procmon.

  8. xcomcmdr says:

    I use ECHO. daily.

    It evens works the same in DOSBox !

    For example :
    @echo off
    echo. ————————————-
    echo. SOME PRESENTATION MESSAGE
    echo. ————————————-
    pause

    will output :
    ————————————-
    SOME PRESENTATION MESSAGE
    ————————————-
    Press Any Key to Continue…

    What I don’t get is how to make ECHO output non-ASCII characters like É properly. But it’s not been enough of a problem to search for the solution, which I’m sure exists.

    1. xcomcmdr says:

      Whoops.
      Why echo. is used here is because echo. permits to put blank lines.

      1. xcomcmdr says:

        Which is, hum, what exactly Raymond said.

        Oops.

        Anyway :
        @echo off
        echo. ÇÀÉçé

        will output :
        Ã└╔þÚ

        But on the command line :
        > echo É
        gives :
        É

        1. David Trapp says:

          I don’t think it’s because of command line vs batch file, I just think that your batch file doesn’t use the same encoding as your shell does. Enter “chcp” in cmd to see which code page is used, and configure your editor to save the file in the same encoding.

          1. xcomcmdr says:

            I used notepad. It was saved with the default encoding : ANSI.

            chcp gives “active code page : 850”

            If the test.bat file is save with UTF-8 encoding, it’s even worse -> even “@echo off” isn’t recognized anymore :

            > D:\Profiles\MNOAL>test.bat

            D:\Profiles\MNOAL>´╗┐@echo off
            ‘´╗┐@echo’ n’est pas reconnu en tant que commande interne
            ou externe, un programme exécutable ou un fichier de commandes.

            D:\Profiles\MNOAL>echo. ├ç├Ç├ë├º├®
            ├ç├Ç├ë├º├®

            And it still won’t output “ÇÀÉçé”.

            Unicode encoding is even worse : it gives up after the first few characters.

        2. David Trapp says:

          In particular, I think you use something like codepage 850 (“DOS-Latin-1”), but your batch file is saved using codepage 819 (“ISO_8859-1”). Use an editor which allows you to select the encoding (e.g. Notepad++) and change it to the same codepage as you see in cmd. This should solve the issue for you.

          1. I guess I found the reason :

            https://blogs.msdn.microsoft.com/oldnewthing/20050308-00/?p=36253/

            But no solution as easy as “don’t use ‘special’ characters in batch files”

        3. Aside from encoding issues, you also need to use a TrueType/OpenType font in your Console window. I usually use Consolas, but Courier New works fine too if you’re old-school.

          The raster font is based on the Terminal bitmap font I think, which has little to no support for non-English characters.

  9. Neil says:

    Most of the workarounds fail if the message begins with \..\ but echo( still works in that case.

  10. I feel like you used to be able to do “echo .” (with the space) to accomplish the same thing, but that no longer works in the Windows command prompt. Either I’m imagining things or the NT codebase changed this implementation detail.

    1. smf says:

      Putting a space between the echo and the . has caused you to get a blank line with just a . at the beginning as far back as dos 3.20

      I saw lots of people do it, because they’d not grasped what the space/lack of space was doing.

Comments are closed.

Skip to main content