Two sets of double quotes batch file error - batch-file

Why does the following batch script fail?
Is it because there are 2 sets of double quotes?
How do I get this to work??
SET INCOME-CODE="test (bob, bob2)"
IF "%INCOME-CODE%"=="NULL" (
SET APCINVOICE=%APCINVOICE%,
) ELSE (
SET APCINVOICE=%APCINVOICE%%INCOME-CODE%,
)

Two things.
First, your variable INCOME-CODE actually has quotes in it. Try this short demonstration:
#echo off
set TEST1="this is a string with spaces"
set "TEST2=this is a string with spaces"
echo %TEST1%
echo %TEST2%
Second, you are comparing to the literal string "NULL". There is no NULL value in batch. Please see this post for more details: What is the proper way to test if variable is empty in a batch file... What you probably want to do is compare to an empty string or use one of the methods in the question above if you're working with something more complex.
IF "%INCOME-CODE%"=="" ( ... )

Related

Cannot manipulate parsed string from another batch file because of space and quote breaking it

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.

How do you add a variable to a string in a batch file?

I can't seem to find how to do this simple task, and this is probably answered.
How does one add a string to a variable? such as set "FileNameAndPCName = Locker\ and add %COMPUTERNAME%" to the variable so it would become like, "Locker/Bill"?
Code:
#echo off
set FileNameAndPCName="Locker\" + "%COMPUTERNAME%"
echo %FileNameAndPCName%
pause
Operations in batch is already string manipulation, therefore you don't need and can't use + to concatenate strings. Just type the whole string like this
set "FileNameAndPCName=Locker\%COMPUTERNAME%"
set FileNameAndPCName="Locker\" + "%COMPUTERNAME%" will set the variable %FileNameAndPCName% to "Locker\" + "%COMPUTERNAME%" literally (after substituting %COMPUTERNAME%. Quotes are not special in the set command. And it's also recommended to use the set "var=value" variant instead of set var=value to avoid unexpected trailing spaces at the end

Is it possible to 'split' the value of a set /p command in cmd?

Is it possible in CMD to partialy extract the value of a string from the set /p var=command and assign each part to some other different variables? I mean, let's say that we used the set /p var= command to read some input from the user, and the user typed in I am Joe . So, now the variable %var%="I am Joe" . Is it possible to assign the "I am" content of %var% to another variable and the "Joe" content to another one as well?
It kind of all depends on what you can expect from the given input. You could use substrings to subtract a fixed part of the input string, like this:
:: part1 = I am
set "part1=%var:~0,4%"
:: part2 = Joe
set "part2=%var:~5,7%"
But if the length of the input string is less than 5, the variable part2 will be undefined. As if you didn't give the variable any value.
:: Like this
set part2=
Another way to get parts of the input string is by tokenizing it. Like this:
for /f "tokens=1-3" %%a in ("%var%") do (
set "part1=%%a %%b"
set "part2=%%c"
)
But there are a couple of problems with this approach that you should be aware of. First of all, since the input is provided by the user it could contain reserved shell characters in combination with doubles quotes and such that could actually break the code. Second, the number of tokens to use and how to deal with them has to be predefined.

Conditional not passing in batch script

I've got a pretty simple batch script, but for some reason the conditional isn't working like I'm expecting:
SET RIG=%1
IF /I RIG==Polar (
SET SQLSERVER=SQL01
SET MONITOR=SQL02
SET TESTSETTING="test"
SET TESTCONTAINER="test2
) ELSE (
ECHO Your input was %1.
)
When I pass the following command: testrun.bat Polar I get the ECHO statement returned: Your input was Polar."
I've tried putting the %1 in quotations, messing with the way parentheses are laid out, and I've reviewed ss64.com's syntax for batch script IF statements, but I just can't figure this one out.
RIGNAME is never going to be equal to Polar
Now you could try assigning the value to rigname rather than rig.
Even then, yu'd need to compare %rigname% to Polar to access the content of rigname rather than the string RIGNAME.

How to add quotes to string in a batch script [duplicate]

This question already has answers here:
Batch PATH with Quotes
(4 answers)
Closed 9 years ago.
Basically I have a variable that has a string in it that is the path to an uninstall program. Sometimes when the variable gets returned it'll return something like
"C:/path to uninstall file/uninstall.exe"
While other times it may return
MsiExec.exe /I{regkeyhere}
Both of those are fine, it's when something like this get's returned
C:/path to uninstall file/uninstall.exe
Where there are no quotes in a file path that causes the call function to fail. Is there anyway to check if the variable begins with a C: and if it does add a quote to the beginning and the end of the string? If it begins with anything other than C: then it doesn't matter, its only if it has a file path with spaces in it that it breaks down. I've tried a couple different string replaces, but for some reason it always breaks down.
Use a caret to escape the quotes:
if "%variable:~0,2%"=="C:" set variable=^"%variable%^"
EDIT: I realised there would be an error if quotes already existed, so this code will create a test variable (with quotes removed) to test the variable first. This code also will not add quotes if there are no spaces.
If it starts with C:, ( If there are spaces don't add quotes, else, add quotes ).
set test=%uninstallStr:"=%
if "%test:~0,2%"=="C:" (
if "%test: =%"=="%test%" (
set uninstallStr=%test%
) else (
set uninstallStr=^"%test%^"
)
)
EDIT 2: I realised there would be more problems with poison characters like < and >, so this code will escape those poison characters first before processing..
set ^"uninstallStr=^"C:\Program Files ^<x86^>\Price Check by AOL\uninstall.exe^"^"
echo %uninstallStr%
set "test=%uninstallStr:"=%"
set "test=%test:<=^<%"
set "test=%test:>=^>%"
if "%test:~0,2%"=="C:" (
if "%test: =%"=="%test%" (
set uninstallStr=%test%
) else (
set uninstallStr=^"%test%^"
)
)
echo %uninstallStr%
pause

Resources