I've been wondering what is the difference between "myvar=me" and "myvar"="me" in a batch file?
It might make a difference to my program which is a rock, paper, and scissors game.
The difference can be easily seen on running a batch file with following lines:
#set "myvar=me"
#set "myvar"="me"
set myvar
#pause
The first line defines an environment variable with name myvar with value me.
The second line defines an environment variable with strange name myvar" with value "me.
The third line is output by Windows command interpreter after preprocessing the command line before execution and outputs all environment variables of which name start with myvar with environment variable name, equal sign and environment variable value.
And fourth line halts batch execution until a key is pressed to see output of third line in case of batch file was executed with a double click.
So the first three lines of output are:
set myvar
myvar=me
myvar"="me
For details on how to define an environment variable right with correct assigning a value read answer on:
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
It explains with text and examples why the syntax set "variable=value" is usually the best.
That depends on context.
In case of usage inside the set command it can treat quotes as a part of a variable name and a value:
>set "a"="111"
'
>set
a"="111
...
But not in this case:
>set "a=111"
'
>set
a=111
...
Internal logic of the cmd.exe is simple is that as it eats character by character and removes quotes from the most left and right parts of a string.
Here is another context (file test.bat):
#echo off
call :TEST "1111"="2222"
call :TEST "1111","2222"
call :TEST "1111";"2222"
call :TEST "1111"-"2222"
exit /b 0
:TEST
echo -%1- -%2-
'
-"1111"- -"2222"-
-"1111"- -"2222"-
-"1111"- -"2222"-
-"1111"-"2222"- --
As you see some characters treated here as a parameter separator in a command line.
Personally I prefer to write the set "var=value" without ^-escape characters before the & and ) characters which can be part of a file path.
Related
I have a batch file which is calling another batch file. batch file 1 is parsing 5 parameters to batch file 2
When I parse the parameters from batch file 1 to batch file 2, it parses correctly but when I assigned those parsed parameters to use them in batch file 2, it breaks.
batch file 1:
ECHO
SET sql=SELECT MAX("Date") FROM SQ_TEST."Sample - Superstore Ran";
SET pref=W
SET num=0
SET day=Friday
SET config=SampleSuperStore.txt
CALL Z:\XXX\RunTableauRefreshAutomatic.bat %sql% %pref% %num% %day% %config%
batch file 2:
CALL C:\XXX\anaconda3\Scripts\activate.bat
SET sql=%~1
SET pref=%~2
SET num=%~3
SET day=%~4
SET config=%~5
C:\XXX\anaconda3\python.exe Z:\XXX\pMainAutomaticDB.py %sql% %pref% %num% %day% %config%
PAUSE
Response from batch file 2:
Z:\XXX>CALL
C:\XXX\anaconda3\Scripts\activate.bat
(base) Z:\XXX>SET sql=SELECT
(base) Z:\XXX>SET
pref=MAX("Date")
(base) Z:\XXX>SET num=FROM
(base) Z:\XXX>SET
day=SQ_TEST."Sample - Superstore Ran"
(base) Z:\XXX>SET config=W
(base)
Z:\XXX>C:\XXX\anaconda3\python.exe Z:\XXX\pMainAutomaticDB.py
SELECT MAX("Date") FROM DL_SQ_TEST."Sample - Superstore Ran" W
(base) Z:\XXX>PAUSE Press any
key to continue . . .
Update: When I remove the double quotes in sql, it works as expected but I need them in it.
Additionally I tried using ^ but the batch file 2 still breaks it differently
#echo off
setlocal
SET "sql=SELECT MAX("Date") FROM SQ_TEST.""Sample - Superstore Ran"";"
call :otherbatch "%sql%" two three
goto :eof
:otherbatch
#echo off
set "var=%~1"
set "var=%var:""="%"
echo one :%var%
echo two :%~2
echo thre:%~3
goto :eof
(it works the same whether calling a separate batch file or a subroutine, so I worked with the latter to show the principle.)
The trick is to ensure the parts with spaces (or other poisonous characters) are properly quoted.
Sadly, this involves some thinking, counting and trying. I see no safe way to automate this (besides a lot of code).
For this special string
SELECT MAX("Date") FROM SQ_TEST."Sample - Superstore Ran";
the string "%sql%" becomes:
"SELECT MAX("Date") FROM SQ_TEST."Sample - Superstore Ran";"
SiiiiiiiiiiiEooooSiiiiiiiiiiiiiiiEoooooooooooooooooooooooSiE
The line below shows, whether a part of the string is inside or outside of proper quoting with Start and End of quoting.
The next step is to ensure each SPACE (or any other delimiter) is quoted (inside) by adding quotes where needed (not around the spaces themselves, but around the substrings that contains them, using the positions of already present quotes).
This changes the string to :
"SELECT MAX("Date") FROM SQ_TEST.""Sample - Superstore Ran"";"
SiiiiiiiiiiiEooooSiiiiiiiiiiiiiiiESiiiiiiiiiiiiiiiiiiiiiiiESoE
Now every space is properly quoted (and you can see, it's difficult as other "unrelated" parts may change their inside/outside status). So it can be passed as a single parameter.
Of course that means, at the receiving side there are some superfluent quotes, which have to be deleted. We can easily (at least for this example) do that by replacing each "" with ":
set "var=%~1"
set "var=%var:""=%"
Note: that's very specific to the string to process, so I tried to explain step by step, what's to be done. You'll have to rethink the whole process for each specific string and I'm sure there are combinations where this approach would be useless.
You have potentially more problems than just spaces!
Poison characters like &, |, >, and < are another problem when passing parameters to a CALLed script. If the desired value is &"&" then it is impossible to pass that value as a literal string without escaping as the unquoted ^&"&" or as a quoted "&"^&"". But escaping dynamic strings is difficult / totally impractical. And sometimes a value must pass through multiple CALLs, each one needing its own round of escaping.
The situation is even worse when passing a caret - It is impossible to pass ^"^". You can double the unquoted ^, but the quoted "^" is a problem because the CALL command doubles quoted ^, and there is absolutely nothing you can do to prevent it. for example CALL ECHO ^^"^" yields ^"^^"!
For anyone doing any advanced scripting, one of the first tricks to learn is to pass values by reference instead of as literals. The calling script stores the value in a variable, and passes the name of the variable to the CALLed script. The CALLed script then uses delayed expansion to access the value. All the nasty batch problems are solved very simply :-)
modified batch file 1:
ECHO
SET sql=SELECT MAX("Date") FROM SQ_TEST."Sample - Superstore Ran";
SET pref=W
SET num=0
SET day=Friday
SET config=SampleSuperStore.txt
CALL Z:\XXX\RunTableauRefreshAutomatic.bat sql %pref% %num% %day% %config%
modified batch file 2:
setlocal enableDelayedExpansion
CALL C:\XXX\anaconda3\Scripts\activate.bat
SET sql=!%~1!
SET pref=%~2
SET num=%~3
SET day=%~4
SET config=%~5
:: I doubt this next line works properly.
C:\XXX\anaconda3\python.exe Z:\XXX\pMainAutomaticDB.py !sql! %pref% %num% %day% %config%
:: You probably need to change your python script to read the sql value from an environment
:: variable so you can then pass the value by reference just as we did with batch.
::
:: C:\XXX\anaconda3\python.exe Z:\XXX\pMainAutomaticDB.py sql %pref% %num% %day% %config%
::
:: Otherwise you will need to escape your quote literals - I believe python uses `\"`
PAUSE
One additional thing to be wary of - String literals containing ! will be corrupted if accessed while delayed expansion is enabled. So in addition to all the "problem" cases listed above, you also should pass by reference if the value may contain !.
Note that your python script also has potential issues with parameters containing " literals. I discuss that in the comments in modified batch 2.
This question already has answers here:
Defining and using a variable in batch file
(4 answers)
Closed 4 years ago.
I set a variable in cmd with the set command, and tried to echo it.
Here is an example:
C:\Users\Logan>set var = text
C:\Users\Logan>set var
var = text
C:\Users\Logan>echo %var%
%var%
C:\Users\Logan>
Is there a way to force the cmd to echo the variable and not the raw text?
Assigning a value/string to an environment variable
It is best to use following syntax with command extensions enabled to define or modify an environment variable:
set "var=text"
The command is set and the parameter is "variable=value".
The parameter string can be enclosed in double quotes as on all commands as long as command extensions are enabled as by default.
If the double quotes are not used around variable=value, command set interprets everything to end of line after the first equal sign including not visible spaces and horizontal tabs at end of line as string value to assign to the variable.
The name of the variable starts with first non whitespace character (after double quote if used) and ends left to first equal sign. The value assigned to the variable starts right of first equal sign and ends at end of line or last double quote.
set VAR = TEXT
The command line above creates an environment variable with name VARSpace and assigns the string SpaceTEXT to this variable.
The usage of
set var="text"
is often not correct as this results in assigning to variable var the text with the quotes included and all trailing spaces and tabs. Referencing now var on another code line with surrounding quotes often results in an error message as the variable holds itself the text already with quotes. For more details see the answer on How to set environment variables with spaces?
Example:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "var=text"
set "var = text"
set "var1=and more text"
set var2="and more text"
set var3="text with 1 trailing space"
set var
echo var3=%var3%^<- Do you see the trailing space?
echo/
set UnwantedSpaceVar=Hello
echo %UnwantedSpaceVar%! ^<- Where does the space come from?
echo/
echo There is a trailing space after Hello in this code snippet.
echo/
set "TrailingSpacesIgnored=Hi"
echo %TrailingSpacesIgnored%! ^<- The 3 trailing spaces above are ignored.
echo/
endlocal
pause
Running this small batch code results in the output:
var=text
var = text
var1=and more text
var2="and more text"
var3="text with 1 trailing space"
var3="text with 1 trailing space" <- Do you see the trailing space?
Hello ! <- Where does the space come from?
There is a trailing space after Hello in this code snippet.
Hi! <- The 3 trailing spaces above are ignored.
Enclosing variable=value in quotes can be done even if the text itself contains 1 or more double quotes.
set "Quote=""
This line defines the variable Quote with the value ". Command set interprets everything after first equal sign left to last double quote as value to assign to variable with name between the first quote and first equal sign.
Note: A string value with " inside and next & or && or || can be even on usage of set "variable=value" misinterpreted and so result in unexpected behavior as it can be seen on running a batch file with following two lines:
#echo off
set "Variable=Value with one double quote in the middle" & echo Oh, there is something wrong here!"
Value with one double quote in the middle" & echo Oh, there is something wrong here! is the string to assign to the environment variable, but assigned to the variable is just Value with one double quote in the middle and the rest of the line after " in the middle and after & interpreted as conditional operator and not literally is interpreted as additional command to execute by cmd.exe. The same problem exists with && or || after a " with 0 or more spaces/tabs between. This problem is not caused by command set. It is caused by Windows command processor which splits the line up into a command line with set and one more command line with echo with conditional execution of the echo command line.
Variable assignment with disabled command extensions
The command syntax set "variable=value" cannot be used if the command extensions are disabled with setlocal DisableExtensions in the batch file (or in Windows registry which is very uncommon and never seen by me on any Windows computer). A syntax error would be the result on execution of the batch file.
It is only possible to use set variable=value with command extensions disabled whereby the value can contain also double quotes and care must be taken on trailing spaces/tabs as they are also assigned to the environment variable.
Run in a command prompt window cmd /? and setlocal /? for more information about command extensions and which commands are affected by command extensions. Note: The output list of affected commands misses exit as described in answers on Where does GOTO :EOF return to?
Variable assignment via arithmetic expression
Using command set with option /A changes completely the parsing of second argument, i.e. the string after set /A. With option /A as first argument the second string is interpreted as arithmetic expression and being therefore processed completely different than on assigning a string value to an environment variable. Environment variables are always of type string and never of type integer.
The usage of option /A requires enabled command extensions as otherwise the command set ignores the rest of the line completely without any error message.
It is in most cases not recommended to just assign a number to an environment variable using an arithmetic expression, i.e. using set /A var=1. set "var=1" or just set var=1 (and no trailing whitespaces) are a little bit faster because environment variables are always of type string.
In an arithmetic expression whitespaces are interpreted as delimiters for variable names, numbers and operators. For that reason the command line set /A var = 1 does not define a variable with name VARSpace with the string Space1 as set var = 1 does. set /A var = 1 defines a variable with name VAR with string value 1 after converting 1 from string (batch file contains 1 as character with hexadecimal code value 31) to integer with value 1 and back to a string with the two values 0x31 and 0x00 (string terminating null).
Variable assignment via a prompt
Also using command set with option /P changes the parsing of the
string after variable name and equal sign. The string after the variable name and the equal sign is interpreted as prompt text to output and not as string to assign to the environment variable.
The environment variable gets assigned the string entered by prompted user (or redirected from a file or command/application), or in case of user does not enter anything before pressing RETURN or ENTER, keeps its current value respectively is still undefined if not defined before the prompt.
The usage of option /P requires enabled command extensions as otherwise the command set ignores the rest of the line completely without any error message.
Most used syntax for prompting a user for a string is:
set /P var="Please enter something: "
The command set removes in this case automatically the double quotes around the prompt text before printing to handle STDOUT (console window if not redirected).
But working is also:
set /P "var=Please enter something: "
Please read this answer for more details about prompt text parsing and how to output a prompt text with surrounding double quotes.
You need to remove whitespace before and after =:
set "var=text"
echo %var%
text
I need help to print an omnibus "summary" string. I have a trigger that executes a procedure:
begin
for each row critical in alerts.status where critical.AlertKey = 'DISK_USAGE_CRIT'
begin
execute send_email( critical.Node, critical.Severity, critical.AlertKey, 'NetcoolEmail', critical.Summary, 'WINITMSVR631');
end;
end
That trigger passes the values of critical node, severity, alertkey, 'NetcoolEmail', summary and host name as parameters to a procedure named send_email.
This is the procedure body:
(node char(1), severity int, situation char(1), email char(1), summary char(1), hostname (1)).
This procedure then passes the values of those parameters to variables in a batch file.
set node=%1
set situation=%3
set summary=%5
echo %node% >> C:\IBM\logtest.txt
echo %situation% >> C:\IBM\logtest.txt
echo %summary% >> C:\IBM\logtest.txt
When I echo all the variables and redirect them into a text file, the summary string is truncated while the others being printed as expected.
This is how summary variable looks if it's fully printed:
DISK_USAGE_CRIT[(%_Used>=1 AND WTLOGCLDSK.INSTCNAME AND Disk_Name="C:" ) ON Primary:WINSVR2K8:NT ON C: (%_Used=41 Disk_Name=C: )]
And yet, it is printed like this:
DISK_USAGE_CRIT[(%_Used
The rest is not being printed.
Why is the summary string not output completely?
Each percent sign % in a string which should be interpreted as literal character within a command process and not as begin/end of an environment variable reference must be doubled.
But if the summary string is passed to batch file as:
"DISK_USAGE_CRIT[(%_Used>=1 AND WTLOGCLDSK.INSTCNAME AND Disk_Name="C:" ) ON Primary:WINSVR2K8:NT ON C: (%_Used=41 Disk_Name=C: )]"
with a double quote at beginning and a double quote at end as last parameter, it is not really necessary to replace each % by %% if using in the batch file additionally delayed environment variable expansion.
The reason for the truncation is > being interpreted as command redirection operator if not found within a double quoted string and not using delayed environment variable expansion.
Therefore it is required here to use delayed expansion on echoing the values of the environment variables containing characters with special meaning for Windows command interpreter.
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set "node=%~1"
set "situation=%~3"
set "summary=%~5"
echo !node!>>C:\IBM\logtest.txt
echo !situation!>>C:\IBM\logtest.txt
echo !summary!>>C:\IBM\logtest.txt
endlocal
See answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line? why using set "variable=value". The first double quote is left to variable name and not right of the equal sign. This makes a big difference as the referenced answer explains in detail.
The space character left of each redirection operator >> is removed to avoid writing a trailing space on each line into the text file. The space character right of each redirection operator >> would not matter, but is here nevertheless removed, too.
For more information about delayed environment variable expansion open a command prompt window, run set /? and read all output help pages for this command very carefully.
This question already has answers here:
Defining and using a variable in batch file
(4 answers)
Closed 4 years ago.
I set a variable in cmd with the set command, and tried to echo it.
Here is an example:
C:\Users\Logan>set var = text
C:\Users\Logan>set var
var = text
C:\Users\Logan>echo %var%
%var%
C:\Users\Logan>
Is there a way to force the cmd to echo the variable and not the raw text?
Assigning a value/string to an environment variable
It is best to use following syntax with command extensions enabled to define or modify an environment variable:
set "var=text"
The command is set and the parameter is "variable=value".
The parameter string can be enclosed in double quotes as on all commands as long as command extensions are enabled as by default.
If the double quotes are not used around variable=value, command set interprets everything to end of line after the first equal sign including not visible spaces and horizontal tabs at end of line as string value to assign to the variable.
The name of the variable starts with first non whitespace character (after double quote if used) and ends left to first equal sign. The value assigned to the variable starts right of first equal sign and ends at end of line or last double quote.
set VAR = TEXT
The command line above creates an environment variable with name VARSpace and assigns the string SpaceTEXT to this variable.
The usage of
set var="text"
is often not correct as this results in assigning to variable var the text with the quotes included and all trailing spaces and tabs. Referencing now var on another code line with surrounding quotes often results in an error message as the variable holds itself the text already with quotes. For more details see the answer on How to set environment variables with spaces?
Example:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "var=text"
set "var = text"
set "var1=and more text"
set var2="and more text"
set var3="text with 1 trailing space"
set var
echo var3=%var3%^<- Do you see the trailing space?
echo/
set UnwantedSpaceVar=Hello
echo %UnwantedSpaceVar%! ^<- Where does the space come from?
echo/
echo There is a trailing space after Hello in this code snippet.
echo/
set "TrailingSpacesIgnored=Hi"
echo %TrailingSpacesIgnored%! ^<- The 3 trailing spaces above are ignored.
echo/
endlocal
pause
Running this small batch code results in the output:
var=text
var = text
var1=and more text
var2="and more text"
var3="text with 1 trailing space"
var3="text with 1 trailing space" <- Do you see the trailing space?
Hello ! <- Where does the space come from?
There is a trailing space after Hello in this code snippet.
Hi! <- The 3 trailing spaces above are ignored.
Enclosing variable=value in quotes can be done even if the text itself contains 1 or more double quotes.
set "Quote=""
This line defines the variable Quote with the value ". Command set interprets everything after first equal sign left to last double quote as value to assign to variable with name between the first quote and first equal sign.
Note: A string value with " inside and next & or && or || can be even on usage of set "variable=value" misinterpreted and so result in unexpected behavior as it can be seen on running a batch file with following two lines:
#echo off
set "Variable=Value with one double quote in the middle" & echo Oh, there is something wrong here!"
Value with one double quote in the middle" & echo Oh, there is something wrong here! is the string to assign to the environment variable, but assigned to the variable is just Value with one double quote in the middle and the rest of the line after " in the middle and after & interpreted as conditional operator and not literally is interpreted as additional command to execute by cmd.exe. The same problem exists with && or || after a " with 0 or more spaces/tabs between. This problem is not caused by command set. It is caused by Windows command processor which splits the line up into a command line with set and one more command line with echo with conditional execution of the echo command line.
Variable assignment with disabled command extensions
The command syntax set "variable=value" cannot be used if the command extensions are disabled with setlocal DisableExtensions in the batch file (or in Windows registry which is very uncommon and never seen by me on any Windows computer). A syntax error would be the result on execution of the batch file.
It is only possible to use set variable=value with command extensions disabled whereby the value can contain also double quotes and care must be taken on trailing spaces/tabs as they are also assigned to the environment variable.
Run in a command prompt window cmd /? and setlocal /? for more information about command extensions and which commands are affected by command extensions. Note: The output list of affected commands misses exit as described in answers on Where does GOTO :EOF return to?
Variable assignment via arithmetic expression
Using command set with option /A changes completely the parsing of second argument, i.e. the string after set /A. With option /A as first argument the second string is interpreted as arithmetic expression and being therefore processed completely different than on assigning a string value to an environment variable. Environment variables are always of type string and never of type integer.
The usage of option /A requires enabled command extensions as otherwise the command set ignores the rest of the line completely without any error message.
It is in most cases not recommended to just assign a number to an environment variable using an arithmetic expression, i.e. using set /A var=1. set "var=1" or just set var=1 (and no trailing whitespaces) are a little bit faster because environment variables are always of type string.
In an arithmetic expression whitespaces are interpreted as delimiters for variable names, numbers and operators. For that reason the command line set /A var = 1 does not define a variable with name VARSpace with the string Space1 as set var = 1 does. set /A var = 1 defines a variable with name VAR with string value 1 after converting 1 from string (batch file contains 1 as character with hexadecimal code value 31) to integer with value 1 and back to a string with the two values 0x31 and 0x00 (string terminating null).
Variable assignment via a prompt
Also using command set with option /P changes the parsing of the
string after variable name and equal sign. The string after the variable name and the equal sign is interpreted as prompt text to output and not as string to assign to the environment variable.
The environment variable gets assigned the string entered by prompted user (or redirected from a file or command/application), or in case of user does not enter anything before pressing RETURN or ENTER, keeps its current value respectively is still undefined if not defined before the prompt.
The usage of option /P requires enabled command extensions as otherwise the command set ignores the rest of the line completely without any error message.
Most used syntax for prompting a user for a string is:
set /P var="Please enter something: "
The command set removes in this case automatically the double quotes around the prompt text before printing to handle STDOUT (console window if not redirected).
But working is also:
set /P "var=Please enter something: "
Please read this answer for more details about prompt text parsing and how to output a prompt text with surrounding double quotes.
You need to remove whitespace before and after =:
set "var=text"
echo %var%
text
I've recently been trying to make a program to simply store text to a file for later viewing, storing it as a .rar file for security against those who don't understand how to extract the text from the .rar (i.e. the less "techy" people)...
I have, however, encountered an error in the program that results in the <word> not expected at this time followed by the .exe closing when I input add/<word> <word>... (i.e. any multi-word string with spaces in between the words [add/<word>, however, does function properly]).
Is there a special rule that must be followed for storing multi-word strings to a .rar or a file in general (I do, however, know that there is a rule for creating/renaming folders/directories)?
The Program Segment:
:command
cls
set /p journal=<journal.rar
echo %journal%
echo.
set /p command=What would you like to do?
cls
if %command%==exit exit
if %command%==help goto help
if %command%==delete echo START; > journal.rar
if %command:~0,4%==add/ echo "%journal%""%command:~4%;" > journal.rar
if %command:~0,5%==edit/ echo %journal:%command:~5%=%;" > journal.rar
goto command
Excuse me. Your question is not clear. There are several confusing points in it, like "followed by the .exe closing" (which .exe is closing?), and the fact that your question is NOT related to .rar files in any way, nor to "storing multi-word strings". However, I can see the following points in it:
When a variable value is expanded with percent signs this way: %command% you must be aware that the variable is first expanded and then the resulting line is parsed. This mean that the value of the variable may introduce errors in the line. For example, in this line: if %command%==exit exit, if the value of command variable is add/one two three, then the line that is parsed is this: if add/one two three==exit exit that, of course, issue an error! (type if /? for further details).
The way to avoid this problem is enclosing both the variable and the comparison value in quotes; this way, if the value have several words with spaces, the whole value is grouped in the IF command for comparison purposes: if "%command%" == "exit" exit. This must be done in every IF command that use the value of the variable.
In the following line:
if %command:~0,5%==edit/ echo %journal:%command:~5%=%;" > journal.rar
you must be aware that the line is parsed from left to right; this means that you can not nest a %variable% expansion inside another one. The way to solve this problem is first complete a %normal% variable expansion, and then a !delayed! variable expansion that will take the previous expanded value. To do that, insert this line at beginning of your program:
setlocal EnableDelayedExpansion
and change previous line by this one:
if "%command:~0,5%" == "edit/" echo !journal:%command:~5%=!;" > journal.rar
For further details, type set /? and carefully read the sections about "delayed expansion".
Here is a sample that can accept multiple words:
set "command="
set /p "command=What would you like to do? "
cls
if /i "%command%"=="have lunch" goto :food