13

Using SET to set an empty value to a variable works nicely in a Windows XP .CMD script. However, the same SET command behaves differently in the same CMD interpreter when used directly from command-line:

Trying to test it in a CMD.EXE command-line:

C:\>set Q=

C:\>echo %Q%
%Q%

C:\>echo "%Q%"
"%Q%"

C:\>set Q=/Q

C:\>echo %Q%
/Q

C:\>echo "%Q%"
"/Q"

Trying to test it with a .CMD script like this:

set Q=
echo %Q%
echo "%Q%"
set Q=/Q
echo %Q%
echo "%Q%"

Running it:

C:\>c.cmd

C:\>set Q=

C:\>echo
ECHO is on.

C:\>echo ""
""

C:\>set Q=/Q

C:\>echo /Q
/Q

C:\>echo "/Q"
"/Q"

What am I missing?

Is that a nice joke from Redmond, or is there any sane explanation for this difference?

How am I supposed to test lines from a .CMD script when they behave differently when used in a command-line?

How do I properly set a variable to an empty string value in a CMD command-line and how do I reference that variable so that I get that empty string?

3
  • Assigning empty string to variable deletes it. I am wondering if set changed its behaviour or the echo did since Windows XP. Is Q variable listed when you run set? Dec 22, 2013 at 15:02
  • @VlastimilOvčáčík: I am talking about Windows XP. SET deletes the variable when issued from the command line. It does not delete the variable when used in a .CMD file. Dec 22, 2013 at 18:56
  • 1
    No, my point is that the set Q= command deletes the variable in both scenarios. Dec 22, 2013 at 21:37

6 Answers 6

8

I met exactly the same problem in my script. Currently I didn't find a way to set a variable to empty string. I just found how to initialize it with one space:

set "Var= "

Those quotation marks are optional. But they really help to see that space explicitly and preserve it in case of terminal whitespace cleanup procedures.

More information you can find here: SET command.

1
  • 1
    I really like this method. The dangling "=" has always bothered me. It breaks the patterns I look for when visually scanning code for errors.
    – KANJICODER
    May 24, 2019 at 23:53
7

tl;dr - Problem you got there is that echo %Q% expands to echo. Use echo.%Q%

Expanded Answer

echo command got 4 behaviors:

  • echo on - enables echoing commands.
  • echo off - disables echoing commands.
  • echo - shows state of echoing commands option.
  • echo ... - puts ... and newline on the screen.

If you pass variable to echo as an argument, and it's empty, it will expand to echo, and will show something like "ECHO is off."

Many people use echo. command to display empty string (read: output newline), but not everybody knows that echo. can be used to excplicitly specify that you want output behavior. e.g.:

  • echo.on - will output on and newline
  • echo.off - will output off and newline
  • echo. - will output newline
  • echo.something - will output something and newline
  • echo.%Q% - will output contents of %Q% whether or not it's ""/"on"/"off" or whatever else.

Keep in mind that there should not be space between . and arguments.

See https://technet.microsoft.com/en-us/library/bb490897.aspx?f=255&MSPPError=-2147217396

4
  • 4
    Because you "tl;dr" you missed the whole gist of the question. ;-) Apr 1, 2015 at 8:38
  • None of this explains why unsetting a variable then attempting to expand it results in no-op at the prompt and empty string in a script. Apr 17, 2017 at 23:03
  • 1
    This doesn't answer the question about how to set a variable to an empty string. Nov 11, 2019 at 9:43
  • Of note: set command= with no quotes and no space seems to wrap around to the next line and overall does very odd things to the script. Apr 14, 2021 at 16:13
3

While you can check whether a variable is empty or not, if you want to concatenate a variable to a string with support for empty/null values, a possible workaround would be to prefix all your values with a dummy character, and skip this character whenever you use this variable:

set q=0
set q2=%q:~1%string

test:

set q=0_
echo %q%
echo %q:~1%concat%q:~1%

set q=0
echo %q%
echo %q:~1%concat%q:~1%

The result will be _concat_ in the first case and concat in the second.

1

@Laszlo Valko: You don't say which CP you use, but I would "fake" the empty variable by using Alt-255, which is an "invisible" character, at least in CP 437. Using your example:

@echo off
::The line below contains the invisible character (Alt-255)
echo Q set to "Invisible"
set Q= 
set Q
echo %Q%
echo "%Q%"
echo Q set to Empty
set Q=
set Q
echo %Q%
echo "%Q%"
echo Q set to "/Q"
set Q=/Q
set Q
echo %Q%
echo "%Q%"

Using SET Q will show you all the variables that start with Q. Try SET C and you'll see what I mean. As you can see, when the variable is set to blank, it is deleted. When you do an ECHO %Q% the command interpreter thinks you're just saying ECHO which then it tells you the state: On or Off. Since I used @echo off at the beginning of the script, it reports that echo is Off.

Hope that helps!

0

I usually do this

set v=""
echo v=%v%  //  <--- v=""

if %v% == ""
0

You can’t test everything that works in a CMD script in an interactive session. They’re too different. Instead, you have to write short one-off scripts. Remember to do all of the setup in your one-off script (such as turning on delayed expansion).

One of those differences is expanding an empty/undefined variable. Another example is how FOR loops work. Labels (and GOTO) are not usable in interactive mode. I could not find a good resource explaining all of these differences—this list is not exhaustive.

FOR interactive:

FOR %A IN (1 2 3) DO ECHO %A

FOR batch file:

FOR %%A IN (1 2 3) DO ECHO %%A

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .