My organization uses batch files to perform queries on our database, and I am presented with a situation in which I need to perform a query which would be much too large to do all at once. So what I've done is modified a batch file to loop through a text file and query each line individually and append the results to the output file.
The problem is when I echo the query variable it reads exactly as expected, but when I pass it to ogr in place of the sql string it seems to be blank. I'm not sure if I'm doing something wrong, or if what I'm trying to do just isn't possible. Can anyone clarify what's going on here?
SET Path=\\my\path\blah\gdal\bin
SET GDAL_DATA=\\my\path\blah\gdal\data
#echo off
SET "file=C:\filepath.txt"
SET /A i=0
REM put file into array line by line
for /F "usebackq delims=" %%a in ("%file%") DO (
set /A i+=1
call set array[%%i%%]=%%a
call set n=%%i%%
)
REM Loop through array entries
for /L %%i in (1,1, %n%) DO (
REM Create SQL String
call set "queryStart="SELECT * FROM _tablename WHERE _fieldname IN ('"
call set uid=%%array[%%i]%%
call set "queryEnd=')""
call set call set "fullQuery=%%queryStart%%%%uid%%%%queryEnd%%"
REM Database Request
ogr2ogr -skipfailures -update -append -s_srs EPSG:4326 -t_srs EPSG:4326 -f "FileGDB" C:\blah\MyExport.gdb PG:"dbname=instagram host=hostservername user=username password=password" -sql %fullquery% -nln "LayerName" -nlt POINT --config FGDB_BULK_LOAD yes
)
pause;
SET Path=\\my\path\blah\gdal\bin;%PATH%
SET GDAL_DATA=\\my\path\blah\gdal\data
#echo off
SET "file=C:\filepath.txt"
SET /A i=0
set "queryStart=SELECT * FROM _tablename WHERE _fieldname IN ^('"
set "queryEnd='^)"
REM put file into array line by line
for /F "usebackq delims=" %%a in ("%file%") DO (
ogr2ogr -skipfailures -update -append -s_srs EPSG:4326 -t_srs EPSG:4326 ^
-f "FileGDB" C:\blah\MyExport.gdb PG:"dbname=instagram host=hostservername user=username password=password" ^
-sql "%queryStart%%%a%queryEnd%" ^
-nln "LayerName" -nlt POINT --config FGDB_BULK_LOAD yes
)
It is not a good idea to remove all elements from path
There is no need to define the start and end of the query in each iteration
You can have problems with the parenthesis in the query, escape them
There is no need for the array, so directly read the file and use the read value in the query.
I have splitted the lines to better read the code. I don't know if ogr2ogr will complain
Not all the changes are needed, of course, just to make it more readable.
And, after all this, if i have to bet, your problem is in the parenthesis. But i can not test it.
Related
I tried searching but couldn't find anything specific to what I need.
So I want to fetch, maybe use curl for Windows, the guid string generated by this website without having to save the html file first. The sources are more or less like this:
<input name="YourGuidLabel" type="text" id="YourGuidLabel" onclick="this.focus(); this.select();" readonly="readonly" class="guidinput" value="852dd74c-4249-4390-85d3-6e9e2116ef2b" /></p>
What I want is this one: 852dd74c-4249-4390-85d3-6e9e2116ef2b. The string is then stored into a variable and echoed to view it.
In linux terminal I can do it in this simple way:
curl -s "https://www.guidgen.com/" | grep -o 'me="YourGuid.*value=.*/>' | cut -d '"' -f14
Does this thing by being able to use a batch file?.
This can do the trick with a batch file on Windows using a PowerShell Command and set it as variable with for /f .. do loop :
#echo off
Title Extract GUID Value from Input Field from site https://www.guidgen.com
#For /f %%a in ('Powershell -C "$(IWR https://www.guidgen.com -UseBasicParsing).InputFields.value"') do Set "GUID=%%a"
Echo GUID=%GUID%
pause
#ECHO OFF
SETLOCAL
rem The following settings for the source directory and filename are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
SET "filename1=%sourcedir%\q74909468.txt"
FOR /f "usebackqdelims=" %%e IN ("%filename1%") DO SET "html=%%e"
SET "html=%html:"=%"
SET "html=%html:<=%"
SET "html=%html:>=%"
SET "html=%html:)=%"
SET "html=%html:(=%"
SET "html=%html:;=%"
FOR %%e IN (%html%) DO if "%%e" neq "//p" SET "guid=%%e"
ECHO GUID=%guid%
GOTO :EOF
Always verify against a test directory before applying to real data.
Note that if the filename does not contain separators like spaces, then both usebackq and the quotes around %filename1% can be omitted.
You haven't told us where the html is located - I've presumed a file.
Sadly "more or less like" is not specific enough to generate a reliable solution.
Read the file line to a variable, html
Remove all " < > ) ( ; from that variable.
process the result, assigning each token in turn to guid, unless the token is //p
Assumes the required string is that string which precedes //p which is the last string in the (original text - deleted character set)
The following idea not using PowerShell may also perform the task you've laid out in your question.
#Echo Off & SetLocal EnableExtensions DisableDelayedExpansion
Set "value=" & For /F Delims^=^ EOL^= %%G In ('%SystemRoot%\System32\curl.exe -s "https://www.guidgen.com" ^| %SystemRoot%\System32\findstr.exe /RIC:" value=\"[0123456789abcdef][0123456789abcdef]*-[0123456789abcdef][0123456789abcdef]*-[0123456789abcdef][0123456789abcdef]*-[0123456789abcdef][0123456789abcdef]*-[0123456789abcdef][0123456789abcdef]*\""') Do (Set "value=%%G" & SetLocal EnableDelayedExpansion & For /F Delims^=^"^= %%H In ("!value:* value=!") Do EndLocal & Set "value=%%H")
If Defined value Echo %value% & Pause
i know this was already discussed but i didn't find what i needed.
I need to add new lines at the end of the hosts window file but,
first i need to check if these lines already exist and than adding them.
I tried this:
set "list=examp.com=examp2.com=examp3.com"
SET NEWLINE=^0.0.0.0
for %%a in (%list%) do (
FINDSTR /I %%a %WINDIR%\system32\drivers\etc\hosts)
IF %ERRORLEVEL% NEQ 0 (ECHO %NEWLINE% %%a>>%WINDIR%\System32\drivers\etc\hosts)
pause
but the result in hosts is just 1 line like this:
0.0.0.0 %a
I also want to know if it's possible to change this:
set "list=examp.com=examp2.com=examp3.com"
with another code that will take variables from a txt file.
Your code is not quite as bad as Mofi would suggest. Although it's quite uncommon to use an equal sign as a delimiter for a for loop, it is nevertheless legal syntax. The largest two problems I see are that you're closing your for loop at the end of your findstr statement; and, assuming you fix that, %ERRORLEVEL% would need its expansion delayed. Or you could use the if errorlevel syntax of the if statement (see help if in a cmd console for full details`). Or even better, use conditional execution.
Here's an example using conditional execution. This example also opens your HOSTS file for appending one time, rather than one time for each loop iteration -- a subtle efficiency improvement, true, but a worthwhile habit to practice when writing files with a loop. And because HOSTS by default has attributes set to prevent writing, I stored and removed the read-only / system / hidden / etc. attributes of the hosts file, appended the changes to the file, then restored the attributes back the way they were before.
#echo off & setlocal
set "hosts=%WINDIR%\system32\drivers\etc\hosts"
set "list=examp.com=examp2.com=examp3.com"
SET "NEWLINE=0.0.0.0"
for /f "delims=" %%I in ('attrib "%hosts%"') do set "raw=%%~I"
setlocal enabledelayedexpansion
for /L %%I in (0,1,18) do if not "!raw:~%%I,1!"==" " set "attrs=!attrs!+!raw:~%%I,1! "
endlocal & set "attrs=%attrs%"
attrib -h -s -r -o -i -x -p -u "%hosts%"
>>"%hosts%" (
for %%a in (%list%) do (
>NUL 2>NUL find /I "%%a" "%hosts%" || echo(%NEWLINE% %%a
)
)
attrib %attrs% "%hosts%"
Although I'm really a newbie in this field, I want to accomplish a task in batch scripting: There is a determinate folder of company contracts in a determinate path, each of this folders (approx. 400) has a common folder (2016) where there might be a file indicating there has been an inspection in this year. What i want is to print every company folder that has not any file in the common 2016 folder and a count of the times this happens.
This is what i have (and does not work at all):
set c=0
for %i /d in (*) do
for %j in ($%i\2016\*) do
if (%j==NUL) then (#echo $%i c+=1 echo %c)`
If you just want to know if there is a file in the 2016 directory you can do this:
#echo off
SetLocal EnableDelayedExpansion
set count=0
for %%i /d in (*) do (
REM first unset variable
set files=
for %%j in (%%i\2016\*) do (
REM will set variable each time a file is encountered
set files=present
)
if not DEFINED files (
REM No files in directory 2016
echo %%i
set /a count+=1
echo !count!
)
)
EndLocal
exit /b 0
I don't see why you use $ before each %i. If you execute this code from the command line use one % for the loop variables i and j. But in a batch-script you'll have to use two of them (%%i, %%j).
Another thing, c+=1 won't work except if you use set /a.
I used delayed expansion because each block code ( between (...)) is parsed as one single command (as if it was all on one line with && between the commands inside the block) and you can't just assign a new value to a variable and read that new value in the same command. That's also the reason why I use !count! instead of %count% (which will give the value before the block). If you'd rather not use delayed expansion, remove the SetLocal EnableDelayedExpansion and replace echo !count! with call echo %%count%% (is another way to read a new value in the same command)
Also, be aware that each echo will end its output with a carriage retur and a newline. So each echo will result in a new line of output.
I want to create a batch file that will read a txt file containing text similar to (it will all be on 1 line):
"http://schemas.google.com/g/2005#event"}],"title":{"$t":"Test Begins","type":"text"},"content":{"$t":"","type":"text"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.google.com/calendar/event?eid=XzhkOWxjZ3JmZHByNmFzams2MWhtNGU5azY4c200cDfr45yxN65kYjE2cGhqNGMxbDY4cjNjZWIxYzhwamNlMzE2Z28wIGFkbWluQGJodWpkaGFtLm9yZw","title":"alternate"},{"rel":"self","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/admin%40test.org/public/full/_8d9lcgrfdpr6asjk61hm4e9k68sm4p336oq62db16phj4c1l63erceb1c8pjce316go0"}],"author":[{"name":{"$t":"admin#test.org"},"email":{"$t":"admin#test.org"}}],"gd$comments":{"gd$feedLink":{"href":"http://www.google.com/calendar/feeds/admin%40test.org/public/full/_8d9lcgrfdpr6asjk61hm4e9k68sm4p336oq62db16phj4c1l68r3ceb1c8pjce316go0/comments"}},"gd$eventStatus":{"value":"http://schemas.google.com/g/2005#event.confirmed"},"gd$where":[{"valueString":""}],"gd$who":[{"email":"admin#test.org","rel":"http://schemas.google.com/g/2005#event.organizer","valueString":"admin#test.org"}],"gd$when":[{"endTime":"2014-01-17","startTime":"2014-01-16"}],"gd$transparency":{"value":"http://schemas.google.com/g/2005#event.opaque"},"gCal$anyoneCanAddSelf":{"value":"false"},"gCal$guestsCanInviteOthers":{"value":"true"},"gCal$guestsCanModify":{"value":"false"},"gCal$guestsCanSeeGuests":{"value":"true"},"gCal$sequence":{"value":0},"gCal$uid":{"value":"CSVConvert0cb9429bdc64a5a6c2052669ab368a40"}},{"id":{"$t":"http://www.google.com/calendar/feeds/admin%40test.org/public/full/_8d9lcgrfdpr6asjk6hh3gphjccpmaphg6opj0d316sq34cj570p3ic1j6grj4opgcoog"},"published":{"$t":"1900-01-01T12:00:00.000Z"},"updated":{"$t":"2013-08-20T11:13:33.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":
The above is a sample of one instance of such chunk of text, the real file could have multiple such chunks.
What i want to do is get the batch script to read the file and when it finds "title":{"$t":"Test Begins","type":"text"} i want Test Begins (in the example above but it could be any text in the real file) to be stored in a variable.
The script should continue reading the text file util it comes across ","startTime":"2014-01-16"}],"gd$transparency" here i want the date stored into a variable.
Now that we have the first pair of variables, i want them to be written to a text file in the following format:
[date] [text]
It keeps doing this until it gets to the end of the file being read.
I have been banging my head over this for a few days a i usually like to learn it without hassling people but i just cant get my head around this.
Your help will be much appreciated.
Batch is not a good option for this problem because it generally cannot handle strings longer than 8191 characters, and your problem looks like it could easily exceed that limit.
A good option is some sort of regex processor. A Windows port of sed or awk would probably do well. There are free versions out there.
I have written REPL.BAT - a hybrid JScript/batch utility that performs a regex search and replace on stdin and writes the result to stdout. It is pure script that will run on any modern Windows machine from XP forward, without the need of any 3rd party executable. Full documentation is embedded within the script.
Assuming REPL.BAT is in your current directory, or better yet, somewhere within your PATH, the following should do the trick.
#echo off
setlocal
set "search=.*?\qtitle\q:{\q\$t\q:\q(.*?)\q,\qtype\q:\qtext\q}.*?\q,\qstartTime\q:\q(.*?)\q}],\qgd\$transparency\q"
type "input.txt" | repl "%search%" "$&\r\n" x | repl "%search%" "[$2][$1]" xa >"output.txt"
I ended up using REPL twice, first to insert a new line at the end of each chunk, and a second time to extract the values from each resultant line. It seems like there should be a one step solution, but I couldn't figure it out.
Update in response to comment
I've also written getTimeStamp.bat - a hybrid JScript/batch utility to compute and format date and time information. Assuming getTimeStamp.bat is in current directory or PATH, then the following will give your desired format.
#echo off
setlocal
set "search=.*?\qtitle\q:{\q\$t\q:\q(.*?)\q,\qtype\q:\qtext\q}.*?\q,\qstartTime\q:\q(.*?)\q}],\qgd\$transparency\q"
>"output.txt" (
for /f "tokens=1,2 delims=[]" %%A in (
'type "input.txt" ^| repl "%search%" "$&\r\n" x ^| repl "%search%" "[$1][$2]" xa'
) do (
set "txt=%%A"
set "dt=%%B"
setlocal enableDelayedExpansion
call getTimeStamp -d "'!dt:-=/!'" -f "{wkd} {dd} {mth}" -r dt
echo [!dt!][!txt!]
endlocal
)
)
Final update in response to comment that has since been deleted
I added one additional REPL to strip out the initial "title":{"$t":"Unwanted Text","type":"text"}
#echo off
setlocal
set "skipSearch=\qtitle\q:\{\q\$t\q:\q.*?\q,\qtype\q:\qtext\q\}((\s|\S)*)"
set "search=.*?\qtitle\q:\{\q\$t\q:\q(.*?)\q,\qtype\q:\qtext\q\}.*?\q,\qstartTime\q:\q(.*?)\q}],\qgd\$transparency\q"
>"output.txt" (
for /f "tokens=1,2 delims=[]" %%A in (
'type "input.txt" ^| repl "%skipSearch%" "$1" mx ^| repl "%search%" "$&\r\n" x ^| repl "%search%" "[$1][$2]" xa'
) do (
set "txt=%%A"
set "dt=%%B"
setlocal enableDelayedExpansion
call getTimeStamp -d "'!dt:-=/!'" -f "{wkd} {dd} {mth}" -r dt
echo [!dt!][!txt!]
endlocal
)
)
Another option, assuming "Calendar" is never a vaild value and should always be discarded, is to use the negative look ahead feature to prevent matching Calendar.
#echo off
setlocal
set "search=.*?\qtitle\q:\{\q\$t\q:\q(?!Calendar\q)(.*?)\q,\qtype\q:\qtext\q\}.*?\q,\qstartTime\q:\q(.*?)\q}],\qgd\$transparency\q"
>"output.txt" (
for /f "tokens=1,2 delims=[]" %%A in (
'type "input.txt" ^| repl "%search%" "$&\r\n" x ^| repl "%search%" "[$1][$2]" xa'
) do (
set "txt=%%A"
set "dt=%%B"
setlocal enableDelayedExpansion
call getTimeStamp -d "'!dt:-=/!'" -f "{wkd} {dd} {mth}" -r dt
echo [!dt!][!txt!]
endlocal
)
)
I don’t know if this is possible but I would like to make a batch, which replaces all, the backslashes contained in a txt file (C:\locations) with forward slashes.
THX..
EDIT:
Im trying to loop:
set str1=!Var1!
echo.%str1%
set str1=%str1:\=/%
to work together with:
set file=C:\text1.txt
FOR /F %%i IN (%file%) DO (
set username=%%i
echo (load "%%i") >> C:\text.txt
)
what I have so far is:
ECHO Retreving list of files...
dir /s /b c:\ICT\AUTOCAD_2010\*.LSP > C:\BART1.txt
Echo Looping variables...
set file=C:\text1.txt
FOR /F %%1 IN (%file%) DO (
set fred=%%1
echo %%1 > C:\tempme.txt
)
set fred=C:\tempme.txt
set fred=%fred:\=/%
echo (load "%fred%") >> C:\text2.txt
however this returns:
(load "C:/tempme.txt")
which is incorect.
Windows' PowerSheel is too limited for that. I suggest you using a scripting language like Perl. Here's a quick script that does that:
my #file = <STDIN>;
my $text = join('', #file);
$text =~ s/\\/\//g;
print($text);
You can launch it like
perl foo.pl < example.txt > result.txt
Using sed as suggested by Tichodroma is another very good option.
I'm a little confused as to what you really want. Your sample code has a FOR ... IN that only has one file in the IN (), i.e. the content of %fred%. Then you write that one filename into a temporary file. Afterwards you have SET that replaces the backslash with a forward slash in the name of the temporary file. But this never touches any file.
However, in your opening segment you want to replace backslashes with forward slashes in a file. So I'm focusing on that part. That would be done this way:
#ECHO OFF
SETLOCAL EnableDelayedExpansion
REM Here's a backslash: \
FOR /F "delims=" %%a IN ('TYPE %0') DO (
SET line=%%a
ECHO !line:\=/!
)
Please note that for simplicity this little batch file parses itself (%0) and, therefore, only replaces that one backslash. However, feel free to put whichever file next to TYPE.
EnableDelayedExpansion makes the syntax with the ! work (see SET /? for more info about delayed expansion). TYPE obviously writes a file to the console. The FOR /F "delims=" now grabs the output of that line per line (since delims= defines no delimiter for the tokenizer of FOR). The line-variable is necessary, because I don't think that there is a proper way to make the ECHO-line work with %%a.
The only downside is that this will remove all empty lines from the original file. I don't know if that's a problem for you.