I am writing a batch script to use an existing environment variable if it exists. If it doesn't, I need to create that environment variable. When the env variable name exists already, the below code runs fine. When the env variable doesn't exist, it just pops up as a flash.
set "my_path=%ENV_VARIABLE_NAME%"
IF %my_path%=="" (
echo no path found
set "my_path = C:/Users/xyz/"
) ELSE (
echo path found
)
pause
Your main problem is the line
IF %my_path%=="" (
When the variable is empty, this is parsed as
IF =="" (
which is incorrect syntax. The parser shows an error message and ends parsing (closing your window when you started it with a double-click).
The proper syntax would be (quoting both sides of the comparison):
IF "%my_path%" == ""
Although I'd prefer #jeb's solution: IF defined my_path (
There is another issue in your code:
set "my_path = C:/Users/xyz/"
sets a variable %my_path % to <space>C:/Users/xyz/ - not what you want. Correct would be:
set "my_path=C:\Users\xyz\"
(Note: the correct path delimiter in Windows is a backslash, not a slash)
The syntax is:
IF defined my_path
See also the help IF /?
This is the mechanism I'd use to perform the task you've provided in your code.
#If Not Defined ENV_VARIABLE_NAME (
Echo No path found.
Set "my_path=C:\Users\xyz"
) Else (
Echo Path found.
Set "my_path=%ENV_VARIABLE_NAME%"
)
Or as a single line without the unnecessary echoing:
#If Not Defined ENV_VARIABLE_NAME (Set "my_path=C:\Users\xyz") Else Set "my_path=%ENV_VARIABLE_NAME%"
Alternatively:
#If Defined ENV_VARIABLE_NAME (
Echo Path found.
Set "my_path=%ENV_VARIABLE_NAME%"
) Else (
Echo No path found.
Set "my_path=C:\Users\xyz"
)
Or as a single line without the unnecessary echoing:
#If Defined ENV_VARIABLE_NAME (Set "my_path=%ENV_VARIABLE_NAME%") Else Set "my_path=C:\Users\xyz"
Of some small note, using IF Defined is not just a different way to check the variable, it is generally a preferable method as it provides two enhanced features:
As it It does not explcitly check the contents of the variable, but instead looks up the name when the command is run.
This means that if the contents of the variable were such that they would have been troublesome to correctly escape it provides no issue..
This also means that the command can be used inside for loops or parenthesis whether or not you use delayed expansion because it's lookup is strictly a command, and so must be done at execution instead of pre-execution
You can also replicate this functionality by using SET | FIND "MYVar=" as again this requires the set command to be run and check the state of the environment at execution, instead of pre-execution.
Related
I have a variable with html code (having major, minor symbols)
and I need it to be exported and appended to a txt
set WORD1=^<p^>^<strong^>PROBLEM^</strong^> with something;n^</p^>
I can't echo the variable like this
echo %WORD1%
And I need to export it/append it to a file. I used:
echo %WORD1% >body.txt
But this generates an error as the variable has minor/Major symbol
If I double quote the variable, the exported text is exported with double quotes (and obviusly this is not what i need)
To define the variable, use:
set "WORD1=<p><strong>PROBLEM</strong> with something;n</p>"
To "export" the variable, use:
(
set /P "=%WORD1%"
echo/
) > body.txt < NUL
To define a variable in a safe way you need to enclose the whole assignment expression in quotation marks:
set "WORD1=<p><strong>PROBLEM</strong> with something;n</p>"
This avoids the need of escaping, unless the string itself contains quotation marks on its own.
Note that this syntax only works with command extensions enabled, but this is the default in Command Prompt anyway.
To return/expand an arbitrary string in a safe manner, even when it contains quotation marks on its own, is to use delayed variable expansion:
echo(!WORD1!
To safely write the output to a file, place the redirection expression at the front:
> "body.txt" echo(!WORD1!
You can also do this on one line:
set "WORD1=<p><strong>PROBLEM</strong> with something;n</p>"&&>body.txt cmd/v/cecho.!WORD1!
rem :: Or, without defining a previous variable, if it is not necessary:
>body.txt <nul set/P "=<p><strong>PROBLEM</strong> with something;n</p>"
I'm trying to replace a string passed as an argument to a batch file.
This works:
set PWD="%~dp1"
set "PWD=%PWD:\=/%"
Which puts the passed argument's parent directory path inside PWD variable, and then replaces \ characters to / characters.
Is there a way to achieve this one liner by execution of just one command instead of two?
Something like this: set "PWD=%~dp1:\=/%, however, that doesn't obviously work.
Please elaborate both methods, using DelayedExpansion and not using it.
Did you test this before posting it?
Your code will produce
PWD=\=/
If it produces the "correct result" then it's because you're not clearing pwd at the end of each run (usually by a setlocal directly after the #echo off) and hence the result will be NOT of the current %~dp1 but of the previous setting of pwd.
Your code first sets pwd to be "c:\whatever..." (including the quotes) PLUS the Space before the & and then sets pwd again to the prior value of pwd with \ replaced by /.
cmd will resolve any expression involving %var% first, and then executes the result. With delayedexpansion, !var! is evaluated at run-time and %var% at parse-time.
Since string-manipulation is not allowed on metavariables, the required operation cannot be condensed into a single statement; the value must be passed through an ordinary environment variable first.
To fix your statement, use
set "PWD=%~dp1" & CALL set "PWD=%%PWD:\=/%%"
which will perform the string-manipulation in a subshell after first assigning the value to pwd - moving the quote delimits the command that will be executed - following spaces after the closing quote will not be included in the value assigned.
This batch file gives the error in the title:
if "%PROCESSOR_ARCHITECTURE%"=="x86" (
echo FOOBAR
) else (
set HOME_EDIT=%SystemDrive%\Program Files (x86)\Notepad++
)
This is on a Win10 Pro x64 system (so the test is false).
Strangely the "set HOME_EDIT..." line, if executed by itself, does NOT generate the error. And this batch file seemed to work OK a few weeks ago (oldest complaint in the book, I know, but maybe the recent Win10 Creator's Update chagned something?).
Here's the whole output:
U:\Users\Dave\data\PC setup\2017-03 PC Setup for Win10>test.bat
\Notepad++ was unexpected at this time.
U:\Users\Dave\data\PC setup\2017-03 PC Setup for Win10> set HOME_EDIT=C:\Program Files (x86)\Notepad++
U:\Users\Dave\data\PC setup\2017-03 PC Setup for Win10>
Putting quotes around the assignment certainly solves the problem, but it has nothing to do with spaces. The problem is the ) in the path is closing the ELSE block prematurely unless the path is quoted (or escaped).
Without quotes, the ELSE block becomes
) else (
set HOME_EDIT=%SystemDrive%\Program Files (x86
)
And then the \Notepad++ is indeed unexpected, causing a syntax error.
I see 3 ways to eliminate the syntax error:
1) Eliminate the parentheses and put the SET command on the same line as ELSE
else set HOME_EDIT=%SystemDrive%\Program Files (x86)\Notepad++
2) Put quotes around the assignment
) else (
set "HOME_EDIT=%SystemDrive%\Program Files (x86)\Notepad++"
)
3) Escape the closing parenthesis
) else (
set HOME_EDIT=%SystemDrive%\Program Files (x86^)\Notepad++
)
If I were to do the assignment, I would use the predefined environment variable for the folder.
) else (
set "HOME_EDIT=%ProgramFiles(x86)%\Notepad++"
)
Answering my own question:
#drescherjm was correct (in the comments) that the immediate problem was lack of quote marks ("foo") around the argument to SET. Somehow this matters when the SET is within a IF statement, even tho it doesn't otherwise.
But adding quotes just broke something else later in my batch script:
set NEW_PATH=%HOME_WINDOWS%
set NEW_PATH=%NEW_PATH%;%BinPath%
set NEW_PATH=%NEW_PATH%;%BinPath%\ffmpeg\bin
set NEW_PATH=%NEW_PATH%;%BinPath%\mplayer
set NEW_PATH=%NEW_PATH%;%BinPath%\gui
set NEW_PATH=%NEW_PATH%;%BinPath%\dll
set NEW_PATH=%NEW_PATH%;%HOME_CYGWIN%\bin
set NEW_PATH=%NEW_PATH%;%HOME_CYGWIN%\sbin
set NEW_PATH=%NEW_PATH%;%HOME_CYGWIN%\usr\bin
set NEW_PATH=%NEW_PATH%;%HOME_CYGWIN%\usr\sbin
set NEW_PATH=%NEW_PATH%;%HOME_7ZIP%
set NEW_PATH=%NEW_PATH%;%HOME_EDIT%
set NEW_PATH=%NEW_PATH%;%HOME_DIFF%
set Path=%NEW_PATH%
setx Path "%NEW_PATH%"
If HOME_EDIT has quote marks in it, this causes SETX to fail.
Here's the fix I came up with (note lines marked with "TRICK1"):
REM The following is a trick to get around spaces in the path (TRICK1)
set HOME_EDIT=%SystemDrive%\%ProgramFiles(x86)%\Notepad++
if "%PROCESSOR_ARCHITECTURE%"=="x86" (
set HOME_CYGWIN=%SystemDrive%\cygwin
set HOME_EDIT=%SystemDrive%\Program Files\Notepad++
) else (
set HOME_CYGWIN=%SystemDrive%\cygwin64
REM (TRICK1 rem this out) set HOME_EDIT=%SystemDrive%\%ProgramFiles(x86)%\Notepad++
)
The path with the spaces in it is SET as a default value prior to entering the IF statement. This way no quote marks are needed, and SETX doesn't break later.
I define variable like:
set LOGGING_MANAGER=-Djuli-logback.configurationFile=file:"%CATALINA_HOME%\conf\logback.xml"
Notice, that I wrap %CATALINA_HOME%\conf\logback.xml in double quotes, because path may contain spaces. And at execution step this variable will substitute to java program.
Example of substitution:
path_to_jre/java.exe %LOGGING_MANAGER%
Next code I can't change: (it's from catalina.bat file from Apache Tomcat)
if not "%LOGGING_MANAGER%" == "" ...
This if statement will fail, because variable contains quotes.
There I have one of 2 problems:
if statement fail (error occured).
without quotes when substitute to java program have problems (space is delimiter).
How can I change variable definition so that the path may contain spaces and if statement will work fine?
note: Not tested, but after reading the catalina.bat this is a way to deal with the problem.
If you are running this from a batch file, you can use
set LOGGING_MANAGER_FILE="%CATALINA_HOME%\conf\logback.xml"
set LOGGING_MANAGER=-Djuli-logback.configurationFile=file:%%LOGGING_MANAGER_FILE%%
set _RUNJAVA=CALL "%JRE_HOME%\bin\java.exe"
call catalina.bat
What it does is
Save the file name with quotes in a separate variable
Set the LOGGING_MANAGER variable using a escaped reference of the previous variable. As it will not be expanded, the final content of the LOGGING_MANAGER variable is -Djuli-logback.configurationFile=file:%LOGGING_MANAGER_FILE%
That way, when the if "%LOGGING_MANAGER%"=="" ... is executed, there will be not any problematic quote.
And now the set _RUNJAVA line. Inside catalina.bat, the contents of the _RUNJAVA are used to initialize the _EXECJAVA variable that will launch the server. _RUNJAVA is initialized in setclasspath.bat IF it has not been initialized by the user (code from setclasspath.bat).
rem Don't override _RUNJAVA if the user has set it previously
if not "%_RUNJAVA%" == "" goto gotRunJava
rem Set standard command for invoking Java.
rem Also note the quoting as JRE_HOME may contain spaces.
set _RUNJAVA="%JRE_HOME%\bin\java.exe"
The default value is "%JRE_HOME%\bin\java.exe", we just add a CALL batch command before to force a second iteration of the batch parser that will expand the quoted %LOGGING_MANAGER_FILE% variable in the final command line.
for %%a in ("%CATALINA_HOME%\conf\logback.xml") do set "LOGGING_MANAGER=-Djuli-logback.configurationFile=file:%%~sa"
should set logging_manager appropriately so that you don't have to "quote the filename"
for %%a in ("%CATALINA_HOME%\conf") do net use o: "\\%userdomain%\sharenameforthedrivewherecatalina_homeisresident%%~pa"
set "LOGGING_MANAGER=-Djuli-logback.configurationFile=file:o:\conf\logback.xml"
may also work - if you know the share name for the drive where catalina_home is resident and assuming o: is an unused drive.
I am trying to create a variable like this in Batch programme:
SET var=abc,def
This command runs fine in command line.
But when I put same line in a batch file it gives error:
def not defined
Is there any other way I can create this string by concatenation or something?
I am basically checking for some directories present under current directory and saving names of present directory comma seperated
this is what my code looks like
SET "dirArray=null"
IF EXIST dir1 (
IF %dirArray% EQU null (
SET "dirArray=src/main"
) ELSE (
SET "dirArray=%dirArray%,dir1"
)
)
... // further more IF EXIST cases for different directories
#Arescet
Has indirectly answered the question
http://www.robvanderwoude.com/escapechars.php
the above link is list of characters that needs to be escaped
, should be escaped as ^,
so replacing set "dirArray=%dirArray%,dir1" with set "dirArray=%dirArray%^,dir1" works
thanks for the help guys