echo Give yearmonth "yyyyMM"
setlocal enabledelayedexpansion
SET /p yearmonth=
SET ClientName[0]=abc
SET ClientName[1]=def
SET i = 0
:myLoop
if defined ClientName[%i%] (
call bq query --use_legacy_sql=false "CREATE EXTERNAL TABLE `test.!ClientName[%%i]!.%yearmonth%` OPTIONS (format = 'CSV',skip_leading_rows = 1 uris = ['gs://test/!ClientName[%%i]!/AWS/%yearmonth%/Metrics/data/*.csv'])"
set /a "i+=1"
GOTO :myLoop
)
Hi, I am trying to create a batch so that i can run Multiple BIG QUERY at once.
Above i tried to write a batch script putting command in a loop .
I am trying to create a table by using yearmonth as user input and then create array to create a table with different client name .
But I am unable to print if i =0 ClientName[i] = abc in a call query i am using !ClientName[%%i]! to print but its not working.
Call query inside loop is not running in GCP console, when i executed the bat file .
Can you please help me resolve this
It is bad practice to set variables as standalone alphabetical characters like i. One reason is exactly as you have experienced, you have confused for metavariable %%i with a set variable %i%.
You are expanding in the loop, but have not enabledelayedexpansion so there are 2 ways, which we will get to in a second.
setting variables should not have spaces before or after = excluding the likes of set /a
So, Method 1, without delayedexpansion (note how the variables are used with double %% in the loop with the call command).
#echo off
echo Give yearmonth "yyyyMM"
SET /p yearmonth=
SET ClientName[0]=abc
SET ClientName[1]=def
SET num=0
:myLoop
if defined ClientName[%num%] (
call bq query --use_legacy_sql=false "CREATE EXTERNAL TABLE `test.%%ClientName[%num%]%%.%yearmonth%` OPTIONS (format = 'CSV',skip_leading_rows = 1 uris = ['gs://test/%%ClientName[%num%]%%/AWS/%yearmonth%/Metrics/data/*.csv'])"
set /a num+=1
GOTO :myLoop
)
Method 2: (better method using delayedexpansion)
#echo off
setlocal enabledelayedexpansion
echo Give yearmonth "yyyyMM"
SET /p yearmonth=
SET ClientName[0]=abc
SET ClientName[1]=def
SET num=0
:myLoop
if defined ClientName[%num%] (
call bq query --use_legacy_sql=false "CREATE EXTERNAL TABLE `test.!ClientName[%num%]!.%yearmonth%` OPTIONS (format = 'CSV',skip_leading_rows = 1 uris = ['gs://test/!ClientName[%num%]!/AWS/%yearmonth%/Metrics/data/*.csv'])"
set /a num+=1
GOTO :myLoop
)
I would go for a more intuitive looping mechanism:
For /F "Tokens=1,* Delims==" %%G In ('"(Set ClientName[) 2>NUL"') Do Call "%ProgramFiles%\Google\Cloud SDK\google-cloud-sdk\bin\bq.cmd" query --use_legacy_sql=false "CREATE EXTERNAL TABLE `test.%%G.%yearmonth%` OPTIONS (format = 'CSV',skip_leading_rows = 1 uris = ['gs://test/%%G/AWS/%yearmonth%/Metrics/data/*.csv'])"
It does not require delayed expansion, or incrementing of variables, and does nothing if no variable named ClientName[n] is defined.
It would therefore mean you could have your variables listed but at some point comment one or more out:
Set "ClientName[0]=abc"
Set "ClientName[1]=def"
Rem Set "ClientName[2]=ghi"
Set "ClientName[3]=jkl"
When the loop ran, unlike in the incrementing mechanism, there would be no unnecessary parsing of a parenthesized If Defined %ClientName[2]% … code block.
However, there are several things in your question which open up the possibility of potential issues. The biggest being that you are seemingly expecting user input, but at the same time trusting that the input is provided, and is formatted according to your expectations. You must always, when writing scripts requiring interaction, assume that the end user cannot or will not always follow the instructions.
Here therefore is a more robustly designed script to perform your intended query:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Rem Define a variable named bq pointing to your bigquery batch file.
Set "bq=%ProgramFiles%\Google\Cloud SDK\google-cloud-sdk\bin\bq.cmd"
Rem If the bigquery batch file does not exist, terminate the script.
If Not Exist "%bq%" Exit /B
Rem Ensure that there are not existing ClientName[n] variables defined.
For /F "Delims=" %%G In ('"(Set ClientName[) 2>NUL"') Do Set "%%G="
Rem Define your ClientName[n] variable list.
Set "ClientName[0]=abc"
Set "ClientName[1]=def"
:GetYearMonth
Rem Ensure that no existing variable named YearMonth is defined.
Set "YearMonth="
Rem Request user input of date saved to the variable named YearMonth.
Set /P "YearMonth=Please provide the date in the format yyyyMM>"
Rem If no input was received, ask again.
If Not Defined YearMonth GoTo GetYearMonth
Rem Remove any doublequotes from the YearMonth variable value.
Set "YearMonth=%YearMonth:"=%"
Rem If YearMonth variable value is not within allowed range, ask again.
Rem This example uses 197001 - 202212
(Set YearMonth) 2>NUL | %SystemRoot%\System32\findstr.exe /R^
/C:"^YearMonth=19[789][0123456789]0[123456789]$"^
/C:"^YearMonth=19[789][0123456789]1[012]$"^
/C:"^YearMonth=20[01][0123456789]0[123456789]$"^
/C:"^YearMonth=20[01][0123456789]1[012]$"^
/C:"^YearMonth=202[012]0[123456789]$"^
/C:"^YearMonth=202[012]1[012]$"^
1>NUL || GoTo GetYearMonth
Rem As input information is valid loop your command.
For /F "Tokens=1,* Delims==" %%G In ('"(Set ClientName[) 2>NUL"'
) Do Call "%bq%" query --use_legacy_sql=false "CREATE EXTERNAL TABLE `test.%%G.%YearMonth%` OPTIONS (format = 'CSV',skip_leading_rows = 1 uris = ['gs://test/%%G/AWS/%YearMonth%/Metrics/data/*.csv'])"
EndLocal
Related
I have the following code;
setlocal EnableDelayedExpansion
:splitEncode
::Get the number of Chapters
set "cmd=FINDSTR /R /N "^.*" %~n1.txt | FIND /C ":""
for /F %%a in ('!cmd!') do set numChapters=%%a
::Cycle through this once for every chapter, getting the line and the line after it
for /L %%a in (1,1,%numChapters%) do (
set "skip="
if %%a geq 2 (
set /a skip=%%a-1
set "skip=skip=!skip!"
)
for /F "!skip! tokens=1,2" %%i in ("%~n1.txt") do (
set startTime=%%i
set chapterName=%%j
)
set "skip=skip=%%a"
for /F !skip! %%i in ("%~n1.txt") do (
set endTime=%%i
)
echo %startTime% %endTime% %chapterName%
)
First I find out how many lines are in a text file, and set that to the variable numChapters.
I then use this to create a for loop that iterates for each chapter.
Inside the for loop, there are two further loops. The first reads a line, and the second reads the following line.
The intent of this is to read lines 1+2, 2+3, 3+4, and use those values as part of a command run the same number of times as the number of lines.
This means that from a list such as this;
00:00:00 The Meeting Room/The Meeting
00:03:36 Long Distance Runaround
00:07:47 Wonderous Stories
I can end up with a command that includes the start time, end time, and chapter title.
The issue I am facing is that no matter what I do, I cannot get the nested for loops to use the skip variables. I've tried %%a, %skip%, !skip!, and none of them work. The value isn't correctly substituted in any situation.
Does anyone have any way to get this variable used, or a better method of reading a specific line of a text file than a for loop?
The option string of for /F (like the root path of for /R) requires immediate (%-)expansion, because for (besides if and rem) is recognised by the command interpreter even before delayed expansion and also expansion of for meta-variables occur.
A possible solution is to put each for /F loop with the dynamic skip options into a sub-routine, to use call to call it and to apply %-expansion therein (see all the additional rem remarks for explanations):
#echo off
setlocal EnableDelayedExpansion
:splitEncode
rem Get the number of chapters
rem // To determine the number of lines in a file you do not need `findstr`:
for /F %%a in ('^< "%~n1.txt" find /C /V ""') do set "numChapters=%%a"
rem Cycle through this once for every chapter, getting the line and the line after it
for /L %%a in (1,1,%numChapters%) do (
set /A "skip=%%a-1"
call :getTwoValues startTime chapterName "%~n1.txt" "!skip!"
call :getTwoValues endTime dummy "%~n1.txt" "%%a"
rem /* For the last line, there is of course no next line containing the end time;
rem therefore, let us mark that case specifically: */
if not defined endTime set "endTime=??:??:??"
rem /* If there is no chapter specified, do not output anything; this might also
rem be quite useful in case the last line just contains a time stamp but no
rem chapter name just to provide the end time of the last one: */
if defined chapterName echo !startTime! !endTime! !chapterName!
)
goto :EOF
:getTwoValues <1st var. name> <2nd var. name> <file path/name> <lines to skip>
rem // Ensure not to return the former output, and set up `skip` option string:
set "%~1=" & set "%~2=" & set /A "skip=0, skip+=%~4" 2> nul
if %skip% gtr 0 (set "skip=skip=%skip%") else set "skip="
rem /* Added `usebackq` in order not to interprete the quoted file path/name as
rem a literal string; also changed the `tokens` option to return the first
rem token and then the whole remainder of the line: */
rem /* Remember that `for /F` regards empty lines for its `skip` option, but it
rem does not iterate through such; hence the first line it iterates over is
rem actually the first non-empty line after the number of skipped lines: */
for /F "usebackq %skip% tokens=1,*" %%i in ("%~3") do (
set "%~1=%%i"
set "%~2=%%j"
rem // Since we do not want to iterate to the last line, leave the loop here:
goto :EOF
)
rem /* This is just needed in case `skip` points beyond the end of the file, or
rem there are no more non-empty lines behind the skipped ones: */
goto :EOF
Based on your sample data, the output should be this:
00:00:00 00:03:36 The Meeting Room/The Meeting
00:03:36 00:07:47 Long Distance Runaround
00:07:47 ??:??:?? Wonderous Stories
However, the entire approach could be heavily simplified, when you avoid the file multiple times and do not read each line twice, by simply reading the file line by line once, but return the chapter information from the previous iteration, together with the end time from the current line:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_FILE=%~n1.txt" & rem // (path/name of file to process)
set "_FRMT=??:??:??" & rem // (dummy end time output for last chapter)
rem /* Initialise variables; loop through lines of files, augmented by
rem an additional line at the end, to alyways output last chapter: */
set "STA=" & for /F "tokens=1,*" %%K in ('
type "%_FILE%" ^& echo(%_FRMT%
') do (
rem // Output the chapter from the previous loop iteration:
set "END=%%K" & if defined STA if defined NAME (
setlocal EnableDelayedExpansion
echo(!STA! !END! !NAME!
endlocal
)
rem // Store chapter information for the next loop iteration:
set "STA=%%K" & set "NAME=%%L"
)
endlocal
exit /B
I am trying to write this Batch script to extract the two parameters from an XML file that looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<!--<var name="SqlConnection" value="data source=SERVERNAME;initialcatalog=DB_NAME;user id=JackDaniels;password=G235X" />-->
<var name="SqlConnection" value="data source=SERVERNAME;initial catalog=DB_Name;Integrated Security=SSPI" />
My objective is to extract SERVERNAME and DB_NAME from the line that is not commented out.
So far my code looks like this:
#echo off
setlocal enableextensions disabledelayedexpansion
set "connectionString="
set result=""
set "INPUT_FILE=DBConnection.config"
FOR /F "tokens=* delims=<var eol=!" %%x in (%INPUT_FILE%) DO (
ECHO %%x
)
PAUSE
I'm just not sure how to get everything right after "data source=" and "initial catalog=". Is there an easy way to do this?
The adequate way to extract this data is not via a Batch file, but with the methods suggested in a comment. However, the Batch file below perform this extraction in a relatively simple way:
#echo off
setlocal EnableDelayedExpansion
rem From the line that have "<var" followed by "value"...
for /F "delims=" %%a in ('findstr "\<var.*value" input.txt') do (
rem ... process the parts separated by space or equal sign, excepting if enclosed in quotes...
for %%b in (%%a) do (
rem ... and store the part after "value" variable
if "!var!" equ "value" set "value=%%~b"
set "var=%%~b"
)
)
rem Separate "value" string at semicolons and assign each part via SET command
for %%a in ("%value:;=" "%") do set %%a
rem Show results:
echo data source=%data source%
echo initial catalog=%initial catalog%
echo Integrated Security=%Integrated Security%
Output example:
data source=SERVERNAME
initial catalog=DB_Name
Integrated Security=SSPI
Of course, if the data format described in the code changes, the program will fail...
#ECHO Off
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q42420941.txt"
FOR %%v IN (initial catalog data source initial_catalog data_source) DO SET "%%v="
FOR /f "delims=<>" %%z IN ('findstr /B /L /C:"\<var name" "%filename1%"') DO (
FOR %%y IN (%%z) DO (
FOR %%a IN (%%~y) DO (
SET "alive=Y"
FOR %%m IN (initial catalog data source) DO IF /i "%%a"=="%%m" SET "alive="&set %%a=Y
IF DEFINED alive (
IF DEFINED initial IF DEFINED catalog SET "initial_catalog=%%a"
IF DEFINED data IF DEFINED source SET "data_source=%%a"
)
IF DEFINED catalog IF NOT DEFINED initial SET alive=y
IF DEFINED source IF NOT DEFINED data SET alive=y
IF DEFINED alive FOR %%v IN (initial catalog data source) DO set "%%v="
)
)
)
ECHO %initial_catalog% and %data_source%
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
I used a file named q42420941.txt containing your data for my testing.
first, clear out the variable-names.
next, parse each line that passes the findstr which is looking for lines that /L literally /B begin with the /c: character-sequence "< escaped by \) and take the first token delimited by > or <.
This neatly strips the awkward <> from the string and assigns the contents of the selected line to %%z
Next, use a simple for to present each token in the line to %%y.
Then with the quotes stripped off of %%y assign each token to %%a.
Search for a match against the keywords, and set the variable of the same name if found. Clear alive if a keyword is found.
If the string in %%a is not one of the keywords, then check to see whether initial and catalog are both set. If so, this is the required string, so assign it.
if catalog is found but not initial then mark as alive
If alive is still set, then we can clear the flags and wait for the start of another sequence.
OK - it has its faults. It won't detect initial_catalog/data_source if either is one of the four keywords (unlikely) and it assumes that the wanted data is the token following the two keywords - the = becomes a separator in the for list.
Since many of you suggested that Batch is not an adequate way of doing this, I decided to play around with PowerShell, and was able to accomplish what I wanted with just a few lines, and some Regex!
$configPath = $PSScriptRoot + "DBConnection.config"
[xml]$XmlDocument = Get-Content -Path $configPath
$dataSource = $XmlDocument.var.Attributes[1].Value.ToString() # Extract the uncommented line, and the second attribute "value"
$serverName = ($dataSource -split 'data source=([^;]*);')[1]
$db_name = ($dataSource -split 'initial catalog=([^;]*);')[1]
$user_id = ($dataSource -split 'id=([^;]*);')[1]
$user_pass = ($dataSource -split 'password=([^;]*)')[1]
I've made a good deal of headway by searching this site and learning the ridiculous language that is Windows batch scripting, but I'm now at a point where I'm stuck. I have a text file with a variable number of lines, each of which looks something like:
AA8315,"United States",N777AN,"American Airlines",AAL98,B772,"Boeing 777-223",AAL,"2013-06-11 23:30:47.923","2013-06-12 00:01:14.459"
My batch file:
set THEDATE=2013-06-12
set THEDATABASE=c:\Kinetic\BaseStation\Basestation.sqb
set THECSVFILE=c:\Flights.csv
set THEOUTPUTFILE=c:\FlightsNew.csv
set THISLINE=""
if exist %THECSVFILE% del %THECSVFILE%
if exist %THEOUTPUTFILE% del %THEOUTPUTFILE%
:: allow time for the csv file to be deleted
timeout /t 2 /nobreak
c:\sqlite3.exe -header -csv %THEDATABASE% "select Aircraft.ModeS, Aircraft.ModeSCountry as Country, Aircraft.Registration as Reg, Aircraft.RegisteredOwners as Owner, Flights.Callsign, Aircraft.ICAOTypeCode as Type, Aircraft.Type as Model, Aircraft.OperatorFlagCode as 'Op Flag', Flights.StartTime as 'First Seen', Flights.EndTime as 'Last Seen' from Aircraft INNER JOIN Flights ON (Aircraft.AircraftID=Flights.AircraftID) where Flights.EndTime like '%THEDATE% %%' order by Flights.EndTime DESC;" >> %THECSVFILE%
::allow time for the csv to be written to file
timeout /t 5 /nobreak
::read %THECSVFILE% and loop through each line
for /F "usebackq tokens=* delims=" %%A in (%THECSVFILE%) do (
set the_line=%%A
call :process_line
)
:process_line
for /F "usebackq tokens=1,2,3,4,5,6,7,8,9,10 delims=[,]" %%1 in (%the_line%) do (
set hexcode=%%1
set country=%%2
set reg=%%3
set owner=%%4
set callsign=%%5
set planetype=%%6
set model=%%7
set opflag=%%8
set firstseen=%%9
set lastseen=%%10
set THISLINE=%hexcode%,%country%,%reg%,%owner%,%callsign%,%planetype%,%model%,%opflag%,%firstseen%,%lastseen%
echo %THISLINE% > %THEOUTPUTFILE%
)
(I'm assigning the tokens to variables because I will be doing additional validation and formatting of them later. I need to get this part working first!)
When executed, the script does indeed loop through each line of the file, however it does not seem to be assigning %%1 to the variable hexcode.
The output of the executed command looks like this:
C:\>for /F "usebackq tokens=1,2,3,4,5,6,7,8,9,10 delims=[,]" %1 in (AA8315 "United States" N777AN "American Airlines" AAL98 B772 "Boeing 777-223" AAL "2013-06-11 23:30:47.923" "2013-06-12 00:01:14.459") do (
set hexcode=%1
set country=%2
set reg=%3
set owner=%4
set callsign=%5
set planetype=%6
set model=%7
set opflag=%8
set firstseen=%9
set lastseen=%10
set THISLINE=,"United States" ,N807FD ,"Fedex Express" ,FDX1378 ,,"Airbus A310-324" ,FDX ,"2013-06-12 22:56:54.639" ,"2013-06-12 23:05:31.822"
echo "" 1>c:\FlightsNew.csv
)
The system cannot find the file AA8315.
Any help is greatly appreciated!
this works here:
for /f "tokens=1-10delims=," %%a in ("AA8315,"United States",N777AN,"American Airlines",AAL98,B772,"Boeing 777-223",AAL,"2013-06-11 23:30:47.923","2013-06-12 00:01:14.459"") do (
set hexcode=%%a
set country=%%b
set reg=%%c
set owner=%%d
set callsegn=%%e
set planefype=%%f
set model=%%g
set opflag=%%h
set firstseen=%%i
set lastseen=%%j
set THISLINE=%%a,%%b,%%c,%%d,%%e,%%f,%%g,%%h,%%i,%%j
)
>"c:\FlightsNew.csv" echo %THISLINE%
I'm not sure, why you need the tokens.
I have always had problems with comma separated values in a for loop. Here's what I did to make your code work.
Test.txt
AA8315,"United States",N777AN,"American Airlines",AAL98,B772,"Boeing 777-223",AAL,"2013-06-11 23:30:47.923","2013-06-12 00:01:14.459"
BatchFile.bat
set THECSVFILE=test.txt
::read %THECSVFILE% and loop through each line
for /F "usebackq tokens=* delims=" %%A in (%THECSVFILE%) do (
set the_line=%%A
call :process_line
)
goto TheEnd
:process_line
for /F "usebackq tokens=1,2,3,4,5,6,7,8,9,10 delims=~" %%1 in ('%the_line:,=~%') do (
set hexcode=%%1
set country=%%2
set reg=%%3
set owner=%%4
set callsign=%%5
set planetype=%%6
set model=%%7
set opflag=%%8
set firstseen=%%9
set lastseen=%%10
set THISLINE=%hexcode%,%country%,%reg%,%owner%,%callsign%,%planetype%,%model%,%opflag%,%firstseen%,%lastseen%
echo %THISLINE% > %THEOUTPUTFILE%
)
:TheEnd
Notice the :process_line for loop. I had to add single quotes around the %the_line% so it didn't try to interpret the string as a filename. Then I replaced all commas with the ~ character, and used the ~ character as the delimiter. It may not work precisely with all your data (if it contains single quotes or the ~ character), but it does work with this one record and gets you moving in the right direction again.
You can only use letters fro the metavariable (%%1 in your code) - but the lower-case and upper-case letters are distinct.
Yes, you can use some other characters, but the contiguous blocks avaliable for "tokens=1-10" (which is an easier version of 1,2,3...) are a..z and A..Z
%0..%9 are reserved for the parameters to the batch or batch-procedure.
If I know that one environment variable contains the name of another, how can I get the value of the second environment variable?
Assume I have a file java.properties alongside my batch file with the following contents.
JAVA_HOME_OVERRIDE_ENV_VAR=JAVA_HOME_1_7_0_17
What I want to do is check if JAVA_HOME_1_7_0_17 is set and, if so, do the equivalent of set JAVA_HOME=%JAVA_HOME_1_7_0_17%. I can figure out what environment variable I'm looking for, but I don't know how to get its value. This is what I have so far...
#echo off
setlocal enabledelayedexpansion
if exist %~dp0\java.properties (
echo "Found java properties."
for /F "tokens=1* usebackq delims==" %%A IN (%~dp0\java.properties) DO (
if "%%A"=="JAVA_HOME_OVERRIDE_ENV_VAR" set JAVA_HOME_OVERRIDE_ENV_VAR=%%B
)
if not [!JAVA_HOME_OVERRIDE_ENV_VAR!] == [] (
echo "Override var is !JAVA_HOME_OVERRIDE_ENV_VAR!"
REM This is where I'm stuck!!!
REM Assume JAVA_HOME_OVERRIDE_ENV_VAR is JAVA_HOME_1_7_0_17
)
)
endlocal & set JAVA_HOME=%JAVA_HOME%
What I want to do is check if the environment variable JAVA_HOME_1_7_0_17 exists and, if it does, use its value to set JAVA_HOME.
Updated
I think the nested if statements are making things more difficult then needed. I got rid of them and the following seems to work.
#echo off
setlocal enabledelayedexpansion
if not exist "%~dp0\java.properties" (
goto:EOF
)
for /F "tokens=1* usebackq delims==" %%A IN ("%~dp0\java.properties") DO (
if "%%A"=="JAVA_HOME_OVERRIDE_ENV_VAR" set JAVA_HOME_OVERRIDE_ENV_VAR=%%B
)
if [!JAVA_HOME_OVERRIDE_ENV_VAR!] == [] (
goto:EOF
)
set JAVA_HOME=!%JAVA_HOME_OVERRIDE_ENV_VAR%!
endlocal & set JAVA_HOME="%JAVA_HOME%"
Try set JAVA_HOME=%!JAVA_HOME_OVERRIDE_ENV_VAR!%.
EDIT: This should not work if !JAVA_HOME_OVERRIDE_ENV_VAR! was set on the same line. Try
call set JAVA_HOME=!%JAVA_HOME_OVERRIDE_ENV_VAR%!
a downside being that since it will search the disk for a file/executable with the name set, the command should take slightly longer to finish, though it should only be noticeable in large loops.
EDIT 2: Try this too...
(add set override=0 in front, add set override=1 under if not, and replace the endlocal line)
#echo off
setlocal enabledelayedexpansion
set override=0
if exist %~dp0\java.properties (
echo "Found java properties."
for /F "tokens=1* usebackq delims==" %%A IN (%~dp0\java.properties) DO (
if "%%A"=="JAVA_HOME_OVERRIDE_ENV_VAR" set JAVA_HOME_OVERRIDE_ENV_VAR=%%B
)
if not [!JAVA_HOME_OVERRIDE_ENV_VAR!] == [] (
echo "Override var is !JAVA_HOME_OVERRIDE_ENV_VAR!"
set override=1
REM Assume JAVA_HOME_OVERRIDE_ENV_VAR is JAVA_HOME_1_7_0_17
)
)
endlocal & if override=1 set JAVA_HOME=!%JAVA_HOME_OVERRIDE_ENV_VAR%!
I would use FINDSTR to filter out the relevant line, IF DEFINED to validate the existence of the variable, and delayed expansion within the loop to get the appropriate value.
Your code could be as simple as:
#echo off
setlocal enableDelayedExpansion
for /f "tokens=1* delims==" %%A in (
'2^>nul findstr /bil "JAVA_HOME_OVERRIDE_ENV_VAR=" "%~dp0\java.properties"'
) do if defined %%B set "JAVA_HOME=!%%B!"
endlocal & set "JAVA_HOME=%JAVA_HOME%"
%params% contains a variable set of arguments:
/tidy /log /truncate /convert D:\libdir
or maybe
/log /tidy D:\cyclea\libfolder /test /convert /truncate
for everything but the (currently single) filepath element I use it such:
if "%params%"=="%params:log=%" goto :DontLogit
if NOT "%params%"=="%params:/tidy=%" (call tidysub: & do something else )
Now I want to extract the filepath element and use it as an argument to a command eg chdir
I've played with, but I'm weak with CMD string manipulation and for loops.
I'd like to keep the order of params variable.
For info it comes from here:
FOR %%s IN (%*) DO (set params=!params! %%s)
#ECHO OFF
SETLOCAL
SET swparams=log tidy test convert truncate
FOR %%i IN (%swparams% other) DO SET "%%i="
FOR %%i IN (%*) DO (
SET "used="
FOR %%p IN (%swparams%) DO (IF /i "/%%p"=="%%~i" SET %%p=Y&SET used=Y)
IF NOT DEFINED used CALL SET other=%%other%% "%%~i"
)
ECHO =============paramsreport===========
FOR %%i IN (%swparams%) DO IF DEFINED %%i (ECHO %%i:set) ELSE (ECHO %%i:clear)
ECHO other=%other%
FOR %%i IN (%other%) DO ECHO %%i or %%~i
GOTO :EOF
Here's a way that should be extensible for you.
Simply set you switch-parameters into the list in swparams.
the parameter-names and OTHER are set to [nothing] to ensure they're not already set in the environment.
Ech supplied parameter is applied to %%i in turn, and matched against each defined swparam in turn. the variable USED is cleared before the match and if the match (of /switchparametername is found, the switch parameter is set and the USED flag is set.
if the used flag is not set gainst any of the switch parameters, then a parsing trick is used to accumulate any unrecognised strings into OTHER
The "%%~i" mechanism first dequotes the item in %%i, then quotes it. In this way, it ends up quoted, regardless of whether it originally has quotes or not.
The /i on the if performs a case-insensitive match.
hence running this batch
thisbatch /tidy "C:\some filename with spaces.txt"
will yield TIDY set to Y, LOG,test, convert, truncate not set and other set to "C:\some filename with spaces.txt"
#echo off
setlocal EnableDelayedExpansion
rem Get the single filepath element (with colon in second character):
set params=/tidy /log /truncate /convert D:\libdir
set filepath=
for %%a in (%params%) do (
set par=%%a
if "!par:~1,1!" == ":" (
set filepath=%%a
)
)
if defined filepath (
echo Filepath = %filepath%
) else (
echo Filepath not given
)
echo/
rem Get multiple filepath elements in an *array*:
set params=/log /tidy D:\cyclea\libfolder /test /convert D:\libdir /truncate
set i=0
for %%a in (%params%) do (
set par=%%a
if "!par:~1,1!" == ":" (
set /A i+=1
set filepath[!i!]=%%a
)
)
echo There are %i% filepath elements:
for /L %%i in (1,1,%i%) do (
echo %%i- !filepath[%%i]!
)
You may review a further description on array management at this post: Arrays, linked lists and other data structures in cmd.exe (batch) script