I'm having an issue on the current project I'm working on.
I have to get a query stored from a file into a variable, whose file only contains a query (It is generated by part of the program). For instance I use the following code:
set /p query=<path\to\my\folder\fileContainingQuery.soql
It works when the query isn't that long, but when its length is beyond 1024 characters, the query is truncated and since I gotta send it to another configuration file using the FART tool, that's quite not convenient.
How to override this problem?
There is a limit in how many data can be stored in a environment variable. In theory, the maximum length is 32767 characters, BUT a batch file cannot set a variable that is longer than the maximum command line length (8192).
You can use a for /f command to read the line
for /f "usebackq delims=" %%f in ("path\to\my\folder\fileContainingQuery.soql") do set "q=%%f"
Or you can generate a auxiliary batch file to assign the content of the query
<nul set/px=set q=>sql.set.cmd
type "path\to\my\folder\fileContainingQuery.soql">>sql.set.cmd
call sql.set.cmd
And both will get the maximum possible text into the variable ONLY if the final command line is not too big (8186 characters in my tests). In other case, nothing is retrieved.
BUT, once the value has been retrieved, is has to be used inside a command. And here the same limitation happens. 8192 is the maximum line length and the content of the variable IS inside the line.
So, your final limit for the length of the query is less than that.
#MC ND: Thanks for your answer, I used the for /f command this way after thinking back at it. (Didn't read your answer at this moment).
(for /f "delims=" %%b in (path\to\my\folder\fileContainingQuery.soql) do (
set query=%%b
))
echo %query%
My hypothesis for my previous problem is that the set /p var function may only accept 1024 characters on user input, and as my query file only contains one line which length could be greater than this limit, it truncates the query. The above code works fine for me and I get my complete query in the variable.
Related
I'm having trouble with a kinda specific problem.
The monitoring software (used for robots in the manufacturing halls) used by the company i am working for, generates a log file (.sdat) every 15 minutes. The content of a log file looks like this:
The syntax: Time;machine;status
13:53:23;KP85;ms:9999
13:53:49;KP85;ms:3
13:54:54;KP85;ms:4
14:06:04;KP85;ms:9999
13:51:38;Robot1;ms:9999
etc...
I've managed to concatenate all the log files into one big file, including the filename at the start of each new row, like this:
The syntax: Filename:Time;Machine;Status
01-03-2016-00-20.sdat:0:07:40;KP65;ms:3
01-03-2016-00-20.sdat:0:09:09;KP65;ms:4
01-03-2016-00-20.sdat:0:09:11;KP65;ms:3
01-03-2016-00-20.sdat:0:09:13;KP65;ms:4
etc..
The reason I did this is because i need the time as well as the date(which is included in the filename) a certain status for a machine has been logged. However, if i import this into SQL management studio, it recognizes 3 columns instead of 4, because the filename and first column(time) are separated by a ':' instead of a ';'. I tried solving it with an SQL Query, separating the date and time with a LEFT() and RIGHT(), but guess what: the time field format changes when the time switches from 9:59:59 to 10:00:00, creating an extra character for the time field (so the data in the column would look like this ':9:59:59', which isn't a valid time field). Perhaps it could be done with SQL but it just seems to me like it would take too much complexity in the SQL code for such a small problem.
So at this point, i thought it would be better to tackle this problem early on; within the batch file which generates the large file, so Management Studio does recognize 4 instead of 3 columns. This is how my .bat file looks like at the moment:
#echo off
findstr "^" *.sdat >output.txt
What do i have to do to get this right?
Thanks in advance,
Mike Sohns
#echo off
(for %%f in (*.sdat) do (
for /f "delims=" %%a in (%%f) do #echo %%f;%%a
))>output.txt
NOTE: this will swallow empty lines, but I think in your case that's not a problem. If yes, the code can be adapted.
Given that all the log files you are concatenating have the sdat extension, you have to replace sdat: for sdat; in order to have a ; separated CSV.
To achieve this, you can use the batch script in this other answer(How to replace substrings in windows batch file), that replaces substrings in a text file using a batch script.
I am looking for some code to extract a number which is expected to be from one to four digits in length from some HTML code. I have pulled the web page using cURL and used FIND to extract the single line of information I need, but I would like the output to be much cleaner.
Here is an example of the HTML line I'm dealing with:
constant_text_here 123 constant_text</h2></td>
Does that html code mess things up for batch scripting? I know nothing about scripting with Windows Batch code. The number can remain as a string, but it is expected to be between one and four digits.
#ECHO OFF
SETLOCAL
FOR /f "tokens=2" %%a IN (q25614455.txt) DO SET var=%%a
ECHO var=%var%
pause
GOTO :EOF
I used a file named q25614455.txt containing your data for my testing. Sadly, you don't reveal what constant_text_here actually is, so honing the procedure is in your bailiwick. The number following tokens= will pick a string from the text supplied in the file; had your text been constant text here for instance, you'd need to change tokens=2 to tokens=4.
It would also likely be possible to include your curl/find into the procedure and extract your target data in one line, but without sufficient details, a vague general question can at best
garner a vague response.
The < and > will give you trouble as they're used to redirect output.
Is using VBscript a possibility?
From the command line:
C:\>set myvar=constant_text_here 123 constant_text</h2></td>
will output:
< was unexpected at this time.
but this will work:
C:\>set myvar="constant_text_here 123 constant_text</h2></td>"
C:\>echo %myvar%
"constant_text_here 123 constant_text</h2></td>"
C:\>echo [%myvar:~20,4%]
[123 ]
Assuming what interests you can always be found at position 20
I am trying to use the FIXED_LENGTH variable within a FOR loop.
Using the length of the string directly in the loop results in correct result, however trying to use the variable does not work. Any ideas?
Snippet that provides correct result
SETLOCAL ENABLEDELAYEDEXPANSION
REM Loop through the input file and read each line.
FOR /F %%G IN (SVN_URLs_List.txt) DO (
SET CUR_LINE=%%G
REM Make sure the variable CUR_LINE is surrounded with ! instead of % to ensure delayed variable expansion.
#ECHO Processing the line: !CUR_LINE!
REM Set fixed length of "https://projects.abcdefg.com/subversion/"
SET FIXED_LENGTH=40
REM Get the sub-string of CUR_LINE to get the folder name.
SET FOLDER_NAME=!CUR_LINE:~40!
#ECHO !FOLDER_NAME!
)
ENDLOCAL
Snippet that does NOT produce correct result:
SETLOCAL ENABLEDELAYEDEXPANSION
REM Loop through the input file and read each line.
FOR /F %%G IN (SVN_URLs_List.txt) DO (
SET CUR_LINE=%%G
REM Make sure the variable CUR_LINE is surrounded with ! instead of % to ensure delayed variable expansion.
#ECHO Processing the line: !CUR_LINE!
REM Set fixed length of "https://projects.abcdefg.com/subversion/"
SET FIXED_LENGTH=40
REM Get the sub-string of CUR_LINE to get the folder name.
SET FOLDER_NAME=!CUR_LINE:~!!FIXED_LENGTH!!!
#ECHO !FOLDER_NAME!
)
ENDLOCAL
I have tried
SET FOLDER_NAME=!CUR_LINE:~!!FIXED_LENGTH!!!
SET FOLDER_NAME=!CUR_LINE:~!FIXED_LENGTH!!
SET FOLDER_NAME=!CUR_LINE:~%FIXED_LENGTH%!
The input in the SVN_URLs_List.txt looks like:
https://projects.abcdefg.com/subversion/svnrepo1
https://projects.abcdefg.com/subversion/svn_repo_2
https://projects.abcdefg.com/subversion/another repo 3
I am expecting result:
svnrepo1
svn_repo_2
another repo 3
The first snippet produces right results.
However using the second snippet produces something like:
https://projects.abcdefg.com/subversion/svnrepo1FIXED_LENGTH
https://projects.abcdefg.com/subversion/svn_repo_2FIXED_LENGTH
https://projects.abcdefg.com/subversion/another repo 3FIXED_LENGTH
SET FOLDER_NAME=!CUR_LINE:~!!FIXED_LENGTH!!!
SET FOLDER_NAME=!CUR_LINE:~!FIXED_LENGTH!!
Wrong syntax. Where does the variable reference begin/end? The parser can not determine it.
SET FOLDER_NAME=!CUR_LINE:~%FIXED_LENGTH%!
Almost, the parse can handle this syntax but bad behaviour. As the variable (FIXED_LENGTH) is assigned its value inside of the for code block, and as the parser replaced the read operation on the variable with its value at parse time (no delayed expansion syntax used to read the variable value) before the variable was assigned its value, the operation will fail.
In your case, instead of defining the FIXED_LENGTH variable inside the for loop, you can define the variable before the for loop, out of it. So, when the block of lines in the do clause of the for command is parsed, the variable will have the adecuated value.
If you prefer/need to declare the variable inside the for loop, you will have to use something like
for %%a in (!FIXED_LENGTH!) do SET FOLDER_NAME=!CUR_LINE:~%%a!
That way the read operation on FIXED_LENGTH is delayed, assigned to the replaceable parameter of the for loop and this parameter is used instead of the variable reference in the substring operation.
Sorry not much experience with batch files hence help needed please! ;-)
I'm working in a DOS box on a Windows 7 64 bit system.
I want to run an application as a batch file, but reading the information it needs from a text file which can be updated/amended regularly.
The syntax of the basic application is:
appname "variable" (the variable MUST be enclosed in quotes)
Successive variables can be concatenated to the following single line format:
appname "var1" "var2" "var3" "var4" ... etc
So I've created a batch file containing the above. However, this is unweildy when it comes to updating. Sometimes I omit the delimiting quotes which creates problems in the execution of the batch file.
It seems to me that from an updating/amending point it would be easier to set up a text file, say text.txt which would contain the following information:
"var1"
"var2"
"var3"
"var4"
etc. on successive lines.
This would make it easier for me to update and also to ensure I don't omit the delimiting quotes.
The batch file would get the application to "read" the text file, execute the first variable, then the second etc all the way through to the end. But I'm not sure if this is possible and if so, how to get the batch file to read successive lines in the text file and use those variables.
As I said earlier, I've not much experience with batch files and don't have a clue how to do this! :-(
Help please, thanks
Alan
Like this :
#echo off
set $textFile="test.txt"
for /f "delims=" %%a in ('type %$textFile%') do appname.exe %%a
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "batchline=appname"
FOR /f "delims=" %%a IN (q25193799.txt) DO SET "batchline=!batchline! "%%~a""
ECHO(%batchline%
GOTO :EOF
I used a file named q25193799.txt containing your data for my testing.
The application line is merely echoed for verification. Remove the ECHO( after verification to execute your application.
The data in the file need not have "enclosing quotes".
Thanks to both responses, both different but good in their own way. I use a few different instances and I've decided to use the first response for the longer lists and the second one for shorter lists (that way I can check see if something is going wrong, because I might have missed the second delimiting quote in the text file.
Superb, thanks to you both.
for /f "tokens=*" %%a in ('find /v ":" "%appdata%\gamelauncher\options.txt" ^| find "menu=a"') do ( set usemenu=a )
for /f "tokens=*" %%a in ('find /v ":" "%appdata%\gamelauncher\options.txt" ^| find "menu=b"') do ( set usemenu=b )
for /f "tokens=*" %%a in ('find /v ":" "%appdata%\gamelauncher\options.txt" ^| find "menu=c"') do ( set usemenu=c )
Right, in this code (which may not work, that what i'm trying to find out) we have this "%%a" in that 'for' command.
First, whats the difference between %variable% and %%a?
Second, can someone explain the 'for' command to me? I have Google'd it way too much and all the explanations seem way to complicated...
What I am trying to do is pull a variable from options.txt, so i can change the menu style of my game launcher. there are 3 styles (a, b and c), so if the options.txt reads "menu=a" how can i get it to set a variable like %usemenu% to the value of a?
Thanks for any help in advance!
%variable% are environment variables. They are set with set and can be accessed with %foo% or !foo! (with delayed expansion if enabled). %%a are special variables created by the for command to represent the current loop item or a token of a current line.
for is probably about the most complicated and powerful part of batch files. If you need loop, then in most cases for has you covered. help for has a summary.
You can
iterate over files: for %x in (*.txt) do ...
repeat something n times: for /l %x in (1, 1, 15) do... (the arguments are start, step and end)
iterate over a set of values: for %x in (a, b, c) do ...
iterate over the lines of a file: for /f %x in (foo.txt) do ...
tokenize lines of a file: for /f "tokens=2,3* delims=," %x in (foo.txt) do ...
iterate over the output of a command: for /f %x in ('somecommand.exe') do ...
That's just a short overview. It gets more complex but please read the help for that.
Variables of the form %%a (or %a if for is used outside of batch files) are very similar to arguments to batch files and subroutines (%1, %2, ...). Some kinds of expansions can be applied to them, for example to get just the file name and extension if the variable represents a file name with path you can use %%~nxa. A complete overview of those is given in help for.
On the other hand, environment variables have other kinds of special things. You can perform replacements in them via %foo:a=b% would result in %foo% except that every a is replaced by a b. Also you can take substrings: %foo:~4,2%. Descriptions of those things can be found in help set.
As to why %variables% and %%a are different things that's a bit hard to answer and probably just a historical oddity. As outlined above there is a third kind of variable, %1, etc. which are very similar to those used in for and have existed for longer, I guess. Since environment variables are a bit unwieldy to use in for due to blocks and thus heavy reliance on delayed expansion the decision probably was made to use the same mechanisms as for arguments instead of environment variables.
Also environment variables could be more expensive, given that the process has a special “environment” block of memory where they are stored in variable=value␀ pairs, so updating environment variables involves potentially copying around a bit of memory while the other kind of variables could be more lightweight. This is speculation, though.
As for your problem, you don't really need for here:
find /v ":" "%appdata%\gamelauncher\options.txt" | find "menu=a" && set usemenu=a
This will only run the set if the preceding command was successful, i.e. menu=a was found. This should be considerably easier than for. From what I read you're trying to look whether menu=a exists in a line that does not contain a colon and in that case usemenu should be set to a, right? (And likewise for b and c. You could try coaxing for into doing that by looping over the lines of the file or output and tokenizing appropriately to figure out the value of menu but depending on the format of the lines this can be tricky. If what you have there works in theory then you should simply stick to that. You can however use a loop around it to avoid having to repeat the same line three times for a, b and c:
for %%X in (a b c) do (
find /v ":" "%appdata%\gamelauncher\options.txt" | find "menu=%%X" && set usemenu=%%X
)
If the file you are parsing is simple, however, with just name=value pairs in each line where : foo would be a comment, then you could use for as well:
for /f "tokens=1,* eol=: delims==" %%A in (%appdata%\gamelauncher\options.txt) do (
if "%%A"=="menu" set usemenu=%%B
)
But that depends a little on the exact format of the file. Above snippet would now read the file line by line and for each line would discard everything after a colon (the eol=: option), use the equals sign as a token delimiter and capture two tokens: The part before the first = and everything after it. The tokens are named starting with %%A so the second one is implicitly %%B (again, this is explained in help for). Now, for each line we examine the first token and look whether it's menu and if so, assign its value to the usemenu variable. If you have a lot of possible options to support this is certainly easier to maintain :-).