I have a project for my Radio Station where I copy the text within a .wsx file of what is on air and parse it to a Audio Processor in my private network for RDS Display using a wget command like
set /p TEXTO= 0<R:\40.wsx
wget -q "http://x.x.x.x:7380/parameter/fm/rds/rds_rt=%TEXTO%" -O NUL
It works great but it won't filter if it's music or promotions.
My challenge is to be able to filter and only parse music names.
For the process I marked the Files that i don't want to show up like commercial, or promotions to start with a "#-" without the quotes.
So the text will show like #-Promo1
My Code:
for /F "delims=" %%a in ('FINDSTR "\<#-.*" C:\RDS\PRUEBAS\txt1.wsx') do set
"VAR=%%a"
echo %VAR%
if "%VAR%" == "true" (
set /p VAR=0<C:\FILEPATH\LOS40.wsx & wget -q
"http://x.x.x.x:7380/parameter/fm/rds/rds_rt=%VAR%" -O NUL
) else (
set /p TEXTO=0<C:\FILEPATH\ENVIVO.wsx & wget -q
"http://x.x.x.x:7380/parameter/fm/rds/rds_rt=%TEXTO%" -O NUL
)
I can't seem to find a correct way to filter it.
pls Heelpp..
for /F "delims=" %%a in ('FINDSTR "\<#-.*" C:\RDS\PRUEBAS\txt1.wsx') do set
should be
for /F "delims=" %%a in ('FINDSTR /b "#-" C:\RDS\PRUEBAS\txt1.wsx') do set
to find those lines in the .wsx file that do /b begin with "#-"
If you want to find those lines that do not begin with "#-" then add /v to the /b.
The result will be a line from the file which does [not] begin with "#-" which will be placed in %%a.
If you simply assign %%a to a variable as you are doing, that variable will contain after the for the last value that was assigned to it.
If you want to execute your wget on each name, then use
for /F "delims=" %%a in ('FINDSTR /B "#-" C:\RDS\PRUEBAS\txt1.wsx') do (
echo %%a
)
and between the parentheses you can execute commands using %%a as a filename.
Quite what you propose to do is obscure. I've no idea what the set/p from an unexplained file is meant to do, but be aware that any code between parentheses is subject to the delayedexpansion trap - please explain what processing you intend to apply to the filenames that do[not] match a leading #-.
You should read SO items on delayed expansion (it's documented with and without the space) to understand the problems with and solutions to processing values that are altered within a loop.
First of all thanks for your help.. I don't have experience in coding.
Let me explain a little bit more..
As I said before its a radio station which will provide text to the Car o home stereos using the RDS Protocol which allow me to send text like song name, title, etc.
Im My case the Audio Processor that let me send the text will receive the info as a URL where I add at the end the text I want to send.
For Example:
http://x.x.x.x:7380/parameter/fm/rds/rds_rt=%TEXTO%
%TEXTO% will be the text Im sending.
C:\RDS\PRUEBAS\txt1.wsx Contains the text of what it being played at the moment and which is being read to see if the #- for the script to avoid sending those titles.
I have a Pc running a Directory Monitor Program that will monitor events on file C:\RDS\PRUEBAS\txt1.wsx and that as soon as being modified, it will execute the batch file CHECKRDS.cmd.
After testing I decided to run a code in CHECKRDS.cmd like:
for /F "delims=" %%a in ('FINDSTR /v "#-" R:\40PPALES.wsx') do (
START "" RDS.bat
)
EXIT
RDS.bat contains code and it works fine:
set /p TEXTO= 0<C:\RDS\PRUEBAS\txt1.wsx
wget -q "http://x.x.x.x:7380/parameter/fm/rds/rds_rt=%TEXTO%" -O NUL
EXIT
As far as the set /p I test it from What does /p mean in set /p?
AS I said before Im new at coding and I just googled everything and started to assable the pieces of the puzzle.
Pls, If you think I should be doing these process diferently, pls let me know..
And sorry for my bad english..
regards
Related
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%"
I know this question has been ask many times, but I've read the answers for hours and tried everything, nothing seems to work. Basically I can't succeed to (Re-)SET a variable in a for /F loop.
I would like to do the following : check the connection between two computers and do an action (basically start a program) if the connection doesn't exist anymore.
#ECHO OFF
SET _A=0
PING localhost | (for /F "tokens=*" %%a in ('FINDSTR Reply') DO #ECHO %%a & SET _A=1)
if %_A%==0 ECHO %_A% FAIL
if %_A%==1 ECHO %_A% SUCCESS
PAUSE
Here I assume that if the PING command doesn't return at least once the word "Reply", then the connection was lost.
The first "DO #ECHO %%a" works, but then it doesn't reset the variable "_A". And I need this variable to be external to the FOR loop because after that the "if %_A%==1" will have to execute the program only once.
Anyone knows what I'm doing wrong ? Thanks a lot for your help. I really tried everything, included setlocal enabledelayedexpansion and putting variable between !!, but nothing works, it always ends up printing "FAIL" and never "SUCCESS".
This is a great question! The problem is the pipe | as this initialises separate termporary cmd instances for both sides. The variable _A is set in the right instance but is lost afterwards.
If you do:
for /F "tokens=*" %%a in ('PING localhost ^| FINDSTR Reply') do #ECHO %%a & SET _A=1
it will work as the set command is in the main cmd instance the batch script is running in.
Note the escaped pipe ^|, which is necessary to transfer its execution to the cmd instance created by for /F for the command line it parses.
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
)
)
This Supybot for windows batch install script needs to create another batch file...
The Problem:
(1) I have a directory that has a file that ends with .conf
(2) There is only one file in this directory that ends with .conf
(3) But I don't know what this file starts with.. all I know is ????????.conf
(4) How do I set the filename.conf and remove the .conf part of the file name?
(5) As it is just the beginning of the filename that I need.
Example:
C:\runbot>find "supybot.ident: " | type *.conf > temp.txt
robotbot.conf
Outputs : robotbot.conf
The quest, is how do I set a variable=robotbot
=========================================================================
The Input was this file named "RootCode.conf" among many others
within the directory searched:
RootCode.conf
The Solution is:
FOR /F "tokens=1,2 delims=." %%a in ('FINDSTR /M "supybot.ident:" *.conf') DO SET USER=%%a&set dontneed=%%b
echo %USER%
pause
The Output is:
C:\runbot>FOR /F "tokens=1,2 delims=." %a in ('FINDSTR /M "supybot.ident:" *.con
f') DO SET USER=%a & set dontneed=%b
C:\runbot>SET USER=RootCode & set dontneed=conf
C:\runbot>echo RootCode
RootCode
C:\runbot>pause
Press any key to continue . . .
Winner... Special thanks Everyone
Your example of piping the output to typecommand is either wrong or useless. So I am assuming you mistyped and the real line was piping the other way around, and thus I am assuming that you are trying to find the filename of the file that contains the string "supybot.ident: ". In that case I would suggest to use findstr command instead.
FOR /F "tokens=*" %%a in ('FINDSTR /M "supybot.ident:" *.conf') DO SET USER=%%a
See HELP FINDSTR, HELP SET and HELP FOR for more information.
It's a bit unclear (to me, at least) what exactly you ask here. But if you need the output of a command, then use for /f:
for /f "delims=" %%x in ('some command ^| line') do set somevar=%%x
Note that you need to escape shell metacharacters in the command line (as they need to survive one parsing pass). Also note that you cannot set a variable to contain more than one line of text.
This question already has answers here:
Set output of a command as a variable (with pipes) [duplicate]
(6 answers)
Closed 7 years ago.
I need to run a simple find command and redirect the output to a variable in a Windows Batch File.
I have tried this:
set file=ls|find ".txt"
echo %file%
But it does not work.
If I run this command it works without problems:
set file=test.txt
echo %file%
So obviously my command output is not being set to my variable. Can anyone help? Thanks
I just find out how to use commands with pipes in it, here's my command (that extracts the head revision of an svn repo) :
SET SVN_INFO_CMD=svn info http://mySvnRepo/MyProjects
FOR /f "tokens=1 delims=" %%i IN ('%SVN_INFO_CMD% ^| find "Revision"') DO echo %%i
First of all, what you seem to expect from your question isn't even possible in UNIX shells. How should the shell know that ls|find foo is a command and test.txt is not? What to execute here? That's why UNIX shells have the backtick for such things. Anyway, I digress.
You can't set environment variables to multi-line strings from the shell. So we now have a problem because the output of ls wouldn't quite fit.
What you really want here, though, is a list of all text files, right? Depending on what you need it's very easy to do. The main part in all of these examples is the for loop, iterating over a set of files.
If you just need to do an action for every text file:
for %%i in (*.txt) do echo Doing something with "%%i"
This even works for file names with spaces and it won't erroneously catch files that just have a .txt in the middle of their name, such as foo.txt.bar. Just to point out that your approach isn't as pretty as you'd like it to be.
Anyway, if you want a list of files you can use a little trick to create arrays, or something like that:
setlocal enabledelayedexpansion
set N=0
for %%i in (*.txt) do (
set Files[!N!]=%%i
set /a N+=1
)
After this you will have a number of environment variables, named Files[0], Files[1], etc. each one containing a single file name. You can loop over that with
for /l %%x in (1,1,%N%) do echo.!Files[%%x]!
(Note that we output a superfluous new line here, we could remove that but takes one more line of code :-))
Then you can build a really long line of file names, if you wish. You might recognize the pattern:
setlocal enabledelayedexpansion
set Files=
for %%i in (*.txt) do set Files=!Files! "%%i"
Now we have a really long line with file names. Use it for whatever you wish. This is sometimes handy for passing a bunch of files to another program.
Keep in mind though, that the maximum line length for batch files is around 8190 characters. So that puts a limit on the number of things you can have in a single line. And yes, enumerating a whole bunch of files in a single line might overflow here.
Back to the original point, that batch files have no way of capturing a command output. Others have noted it before. You can use for /f for this purpose:
for /f %%i in ('dir /b') do ...
This will iterate over the lines returned by the command, tokenizing them along the way. Not quite as handy maybe as backticks but close enough and sufficient for most puposes.
By default the tokens are broken up at whitespace, so if you got a file name "Foo bar" then suddenly you would have only "Foo" in %%i and "bar" in %%j. It can be confusing and such things are the main reason why you don't ever want to use for /f just to get a file listing.
You can also use backticks instead of apostrophes if that clashes with some program arguments:
for /f "usebackq" %%i in (`echo I can write 'apostrophes'`) do ...
Note that this also tokenizes. There are some more options you can give. They are detailed in the help for command.
set command has /p option that tells it to read a value from standard input. Unfortunately, it does not support piping into it, but it supports reading a value from a first line of existing file.
So, to set your variable to the name of a first *.txt file, you could do the following:
dir /b *.txt > filename.tmp
set /p file=< filename.tmp
del /q filename.tmp
It is important not to add a space before or even after =.
P. S. No fors, no tokens.
Here's a batch file which will return the last item output by find:
#echo off
ls | find ".txt" > %temp%\temp.txt
for /f %%i in (%temp%\temp.txt) do set file=%%i
del %temp%\temp.txt
echo %file%
for has a syntax for parsing command output, for /f "usebackq", but it cannot handle pipes in the command, so I've redirected output to a temporary location.
I strongly recommend, given that you have access to ls, that you consider using a better batch language, such as bash or even an scripting language like python or ruby. Even bash would be a 20x improvement over cmd scripting.
The short answer is: Don't!
A windows shell env var can hold a max of 32 Kb and it isn't safe to save output from programs in them.
That's why you can't. In batch script you must adopt another programming style. If you need all of the output
from the program then save it to file. If you only need to check for certain properties then pipe the output into
a program that does the checking and use the errorlevel mechanism:
#echo off
type somefile.txt | find "somestring" >nul
if %errorlevel% EQU 1 echo Sorry, not found!
REM Alternatively:
if errorlevel 1 echo Sorry, not found!
However, it's more elegant to use the logical operators Perl style:
#echo off
(type somefile.txt | find "somestring" >nul) || echo Sorry, not found!
It's not available in DOS, but in the Windows console, there is the for command. Just type 'help for' at a command prompt to see all of the options. To set a single variable you can use this:
for /f %%i in ('find .txt') do set file=%%i
Note this will only work for the first line returned from 'find .txt' because windows only expands variable once by default. You'll have to enable delayed expansion as shown here.
what you are essentially doing is listing out .txt files. With that, you can use a for loop to over dir cmd
eg
for /f "tokens=*" %%i in ('dir /b *.txt') do set file=%%i
or if you prefer using your ls, there's no need to pipe to find.
for /f "tokens=*" %%i in ('ls *.txt') do set file=%%i
Example of setting a variable from command output:
FOR /F "usebackq" %%Z IN ( `C:\cygwin\bin\cygpath "C:\scripts\sample.sh"` ) DO SET BASH_SCRIPT=%%Z
c:\cygwin\bin\bash -c '. ~/.bashrc ; %BASH_SCRIPT%'
Also, note that if you want to test out the FOR command in a DOS shell, then you need only use %Z instead of %%Z, otherwise it will complain with the following error:
%%Z was unexpected at this time.