1

I wrote the following:

@ECHO OFF

SET v1old=4
SET v2old=0
SET v3old=7453
SET v1new=83
SET v2new=645
SET v3new=2
SET bug=SET

ECHO @ECHO OFF ^& SETLOCAL>>newupdate.bat
ECHO REM .>>newupdate.bat
ECHO REM version von dolphin>>newupdate.bat
ECHO %bug% v1old=%v1new%>>newupdate.bat
ECHO %bug% v2old=%v2new%>>newupdate.bat
ECHO %bug% v3old=%v3new%>>newupdate.bat
ECHO %bug% bug=%bug%

PAUSE
EXIT

The following line will be shown in console instead of beeing written into the bat file:

ECHO %bug% v3old=%v3new%>>newupdate.bat

The variable v3new stores a value from 0-9 if I let them store something other like chars, signs or values with more then 1 digit it will work...

I want that the script mutates himself where only the first lines will change. So I want to write the first lines to a new file...

Why does it not work, is that a bug or do I do something wrong?

aschipfl
  • 33,626
  • 12
  • 54
  • 99
Regda
  • 11
  • 1
  • 1
  • 9

4 Answers4

2

Solutions

The answer by Seth McCauley works fine for the echo-ed set lines.

An alternative and more generic solution is to put every echo within parentheses like this, hence the original set string is redirected without any modification:

(ECHO %bug% v3old=%v3new%)>>newupdate.bat

Another yet worse possibility is to insert a single SPACE before redirection >/>>; this prevents the line from being displayed in the console window, but the SPACE is redirected as well (and, when newupdate.bat is executed, it will be assigned to the variable value as well).


Root Cause

The problem is the combination of characters that appear in the failing echo line (the third one here):

ECHO %bug% v1old=%v1new%>>newupdate.bat
ECHO %bug% v2old=%v2new%>>newupdate.bat
ECHO %bug% v3old=%v3new%>>newupdate.bat

Remove @echo off from the top of your batch script temporarily and you will see what command line is echoed to the console respectively:

ECHO SET v1old=83 1>>newupdate.bat
ECHO SET v2old=645 1>>newupdate.bat
ECHO SET v3old= 2>>newupdate.bat

The console shows the unwanted response, which is not written to newupdate.bat unintentionally:

SET v3old=

This is because of the character substring =2>> in the expanded and echoed command. Why:

  1. = acts as a separator, like also SPACE, ,, ;.
  2. Because of the preceding separator =, 2>> is treated as the redirection operator.
  3. 2, since it is a one-digit number immediately preceding >>, is taken as a handle for redirection, where 2 means STDERR (1 is STDOUT, the default for >/>>; 0 is STRIN, 3 - 9 are undefined).

All this means that STDERR is redirected into newupdate.bat rather than the echo-ed line which appears at STDOUT (handle 1). STDERR carries no data here so nothing goes to the file.
For the other lines, as at least one of the above listed conditions is violated, redirection is not modified unintentionally, so >> (same as 1>>) is applied, so STDOUT is redirected into the file and STDERR goes to the console but is empty anyway.

So STDOUT carries the following data with respect to the above three lines:

SET v1old=83
SET v2old=645

Note that without redirection, both STDOUT and STDERR were passed to the console as per default.

Reference this resource for the redirection syntax and this post for a great explanation of redirection.

Conclusion

Since there is a separator (one of SPACE, ,, ;, =) followed by a variable string portion followed by redirection signs >>, it could happen that unintended redirections occur, when the said central string becomes a single decimal figure.

All of the solutions presented on top of this answer (including the referenced one) work because there is a character inserted in between the redirection mark >> and the preceding string portion.

Community
  • 1
  • 1
aschipfl
  • 33,626
  • 12
  • 54
  • 99
1

Here are two modern methods to echo into a file without trailing spaces:

Note the first redirection only has one > to create or overwrite the file.

@ECHO OFF

SET v1old=4
SET v2old=0
SET v3old=7453
SET v1new=83
SET v2new=645
SET v3new=2
SET bug=SET

 >newupdate.bat ECHO @ECHO OFF ^& SETLOCAL
>>newupdate.bat ECHO REM .
>>newupdate.bat ECHO REM version von dolphin
>>newupdate.bat ECHO %bug% v1old=%v1new%
>>newupdate.bat ECHO %bug% v2old=%v2new%
>>newupdate.bat ECHO %bug% v3old=%v3new%
ECHO %bug% bug=%bug%

PAUSE
EXIT

This method is very useful, but ) need to be escaped to ^) also

@ECHO OFF

SET v1old=4
SET v2old=0
SET v3old=7453
SET v1new=83
SET v2new=645
SET v3new=2
SET bug=SET

(
ECHO @ECHO OFF ^& SETLOCAL
ECHO REM .
ECHO REM version von dolphin
ECHO %bug% v1old=%v1new%
ECHO %bug% v2old=%v2new%
ECHO %bug% v3old=%v3new%
)>newupdate.bat
ECHO %bug% bug=%bug%

PAUSE
EXIT
foxidrive
  • 40,353
  • 10
  • 53
  • 68
0

The batch echo command has a variety of issues displaying certain content. Putting double quotes around the SET statements will resolve the issue you are experiencing. You may also want to change your first file redirection to use > instead of >>, so that the batch file is overwritten each time instead of appended to. Here is the updated code:

@ECHO OFF
SET "v1old=4"
SET "v2old=0"
SET "v3old=7453"
SET "v1new=8"
SET "v2new=645"
SET "v3new=2"

ECHO @ECHO OFF ^& SETLOCAL>newupdate.bat
ECHO REM .>>newupdate.bat
ECHO REM version von dolphin>>newupdate.bat
ECHO SET "v1old=%v1new%">>newupdate.bat
ECHO SET "v2old=%v2new%">>newupdate.bat
ECHO SET" v3old=%v3new%">>newupdate.bat

PAUSE
EXIT
Seth McCauley
  • 983
  • 11
  • 24
0

This is happening because v3new is 2. So you are directing STDERR to newupdate.bat. Easy way for you to see that is to temporarily comment out the @ECHO OFF and you will see that the line in question expands to

ECHO SET v3old= 2>>newupdate.bat

@Seth has good suggestions but you will still have the problem. Inserting a space between > and newupdate.bat in each case would solve the problem.

RGuggisberg
  • 4,630
  • 2
  • 18
  • 27