I want to run more than 1 command with the FOR /F - batch-file

I'm trying to make a script to:
send a request to an url, then append (>>) the %%a variable i set in the FOR /F command IF i get a certain response from the command i run with FOR /F.
I tried with 2 scripts that are the followings:
FOR /F %%a in (usernames.txt) do (
IF "curl -k -d name=%%a https://club.pokemon.com/api/signup/verify-username" EQU "{"valid":true,"suggestions":[],"inuse":false}" %%a >> usernames1.txt
and
set /p VAR = < tmpFile
FOR /F %%a in (usernames.txt) do (
curl -k -d name=%%a https://club.pokemon.com/api/signup/verify-username
> tmpFile
IF VAR={"valid":true,"suggestions":[],"inuse":false}
%%a >> usernames1.txt)
EDIT: good enough with that script, thanks guys. but i've got another thing: can i add more than 1 variable to the script? I mean a variable like %%a, that takes every line from another txt file

First, you set VAR once, whereas your temporary file does not exist. Then you test with = instead of == and without the ! chars.
And don't put too many spaces like if you were using a real shell like bash :)
As Magoo noted, I also had to fix set /p VAR = < tmpFile to remove the extra spaces. Batch has a tendency to take them literaly.
(another example: echo foo > file: file now contains "foo ".
(needless to say that without enabledelayedexpansion it wouldn't work either because lots of things happen inside the FOR loop)
The fixed code (also had to protect the test string with extra quotes or it wouldn't work):
setlocal enabledelayedexpansion
del usernames1.txt >NUL 2>NUL
FOR /F %%a in (usernames.txt) do (
curl -k -d name=%%a https://club.pokemon.com/api/signup/verify-username > tmpFile 2>NUL
set /p VAR=<tmpFile
IF "!VAR!"=="{"valid":true,"suggestions":[],"inuse":false}" echo %%a >> usernames1.txt
)
I tested it with a random list of user names and changing "valid":true by "valid":false and the names were issued.

Related

Batch Script To Fetch Website and Parse String

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

how to add new lines to windows hosts with a batch file

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%"

Extract the sub string from end offline to a special character in batch file

HI i am trying to get the sub string ZoomIn10X,ZoomIn20X,ZoomIn30X etc, from a file which contain following lines below and out put that to another file
Job Name : STANALONE/1234/JobId/Date/ZoomIn10X
Job Name : STANALONE/1234/JobId/Date/ZoomIn20X
Job Name : STANALONE/JobId/Date/ZoomIn30X
Job Name : STANALONE/1234/JobId/Date/ZoomIn40X
Job Name : STANALONE/1234/Date/ZoomIn10X
i Have tried
for /F "tokens=*" %%A in (input.txt) do (
echo %%A r "/" "\n" %%A | tail -1 >> output.txt
)
but its not working as properly.Can you please help
on unix, with perl
perl -pe 's#.*/##' input.txt
see perl -h for options and perlop regex for more details.
habitually substitute expressions are written with a / forward slash delimiter but any other character can be used as in sed. here using # to avoid escaping /.
or with shell language bash (slower because of bash read)
while read -r line; do
echo "${line##*/}"
done <input.txt
see bash variable expansion. here ## to remove the longest prefix.
>output.txt (for /f "delims=" %%a in (input.txt) do echo %%~nxa)
Given the input lines, and handling them as paths+files references (yes, they are not, but can be handled as if they were), using the for replaceable parameter modifiers (see for /?) we request the name and extension of the file being referenced. All the output of the for execution is redirected to output.txt.
[W:\44365640]:# type go.cmd
#echo off
setlocal enableextensions disabledelayedexpansion
>output.txt (for /f "delims=" %%a in (input.txt) do echo %%~nxa)
[W:\44365640]:# type input.txt
Job Name : STANALONE/1234/JobId/Date/ZoomIn10X
Job Name : STANALONE/1234/JobId/Date/ZoomIn20X
Job Name : STANALONE/JobId/Date/ZoomIn30X
Job Name : STANALONE/1234/JobId/Date/ZoomIn40X
Job Name : STANALONE/1234/Date/ZoomIn10X
[W:\44365640]:# go
[W:\44365640]:# type output.txt
ZoomIn10X
ZoomIn20X
ZoomIn30X
ZoomIn40X
ZoomIn10X
[W:\44365640]:#
Using awk you could define / as field separator and output the last field:
$ awk -F/ '{print $NF}' input.txt
ZoomIn10X
ZoomIn20X
ZoomIn30X
ZoomIn40X
ZoomIn10X
Solution outputs the last field of every line, including the empty lines you had between the data lines. If you need to filter the output somehow, please update the requirements to the OP.
I think the others answers are not using batch only syntax.
The following solution should work if you have the input.txt file as you have written (I have added even option to use the solution as variable):
EDIT:
Added comments for the script:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
REM your input.txt file looks like this
REM Job Name : STANALONE/1234/JobId/Date/ZoomIn10X
REM Job Name : STANALONE/1234/JobId/Date/ZoomIn20X
REM Job Name : STANALONE/JobId/Date/ZoomIn30X
REM Job Name : STANALONE/1234/JobId/Date/ZoomIn40X
REM Job Name : STANALONE/1234/Date/ZoomIn10X
REM if you wished to use variable
REM SET final_name=""
FOR /F "tokens=2 delims=:" %%A IN (input.txt) DO (
SET temp_var=%%A
FOR /F "tokens=4 delims=/" %%B IN ("!temp_var!") DO (
SET temp_var_B=%%B
IF "!temp_var_B!" EQU "Date" (
FOR /F "tokens=5 delims=^/" %%C IN ("!temp_var!") DO (
ECHO %%C >> output.txt
REM if you wished to use variable
REM SET final_name=!final_name!,%%C
)
) ELSE (
ECHO %%B >> output.txt
REM if you wished to use variable
REM SET final_name=!final_name!,%%B
)
)
)
ECHO All collected variables: !final_name!
ENDLOCAL
This is somewhat inefficient solution, much better you can find below, but collects also variables. It uses the fact that you can split string multiple times and if you have different string length you can still extract it based on the string, if it is the same, like in your case a "Date". First FOR splits the string based on ":" character and the other FORs based on "/" char. There are two FORs as you have different length of the extracted string.
EDIT :
I think I was too quick to find a solution. When I thought about it I recognized it as very "crude" solution. I'll also comment it better as I have posted only the code.
The more efficient solution:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
REM your input.txt file looks like this
REM Job Name : STANALONE/1234/JobId/Date/ZoomIn10X
REM Job Name : STANALONE/1234/JobId/Date/ZoomIn20X
REM Job Name : STANALONE/JobId/Date/ZoomIn30X
REM Job Name : STANALONE/1234/JobId/Date/ZoomIn40X
REM Job Name : STANALONE/1234/Date/ZoomIn10X
FOR /F "tokens=2 delims=:" %%A IN (input.txt) DO (
SET var=%%A
IF EXIST input.txt (
ECHO !var:~-9! >> output.txt
) ELSE (
ECHO !var:~-9! > output.txt
)
)
ENDLOCAL
Description:
First comes the FOR /F with "tokens=2" (takes a second part) and "delims=:" uses a ":" as delimiter.
The core of the solution uses the fact that you have at the end constant size string (9 characters to be exact) which you want to extract - !var:~-9!. Uses expanded variable and takes 9 characters from the end of the string which was selected with the FOR statement.
The solution needs to have the SETLOCAL ENABLEDELAYEDEXPANSION there as it uses the expansion.
There is also a IF EXISTS clause so it will create a new file every time you run it. That is not a vital part of the script and you may comment it out.

how to set a variable for the value of " ping 8.8.8.8 | find /c "TTL=" " [duplicate]

This question already has answers here:
Assign output of a program to a variable using a MS batch file
(12 answers)
Closed 9 months ago.
I'm trying to assign the output of a command to a variable - as in, I'm trying to set the current flash version to a variable. I know this is wrong, but this is what I've tried:
set var=reg query hklm\SOFTWARE\Macromedia\FlashPlayer\CurrentVersion>
or
reg query hklm\SOFTWARE\Macromedia\FlashPlayer\CurrentVersion >> set var
Yeah, as you can see I'm a bit lost. Any and all help is appreciated!
A method has already been devised, however this way you don't need a temp file.
for /f "delims=" %%i in ('command') do set output=%%i
However, I'm sure this has its own exceptions and limitations.
This post has a method to achieve this
from (zvrba)
You can do it by redirecting the output to a file first. For example:
echo zz > bla.txt
set /p VV=<bla.txt
echo %VV%
You can't assign a process output directly into a var, you need to parse the output with a For /F loop:
#Echo OFF
FOR /F "Tokens=2,*" %%A IN (
'Reg Query "HKEY_CURRENT_USER\Software\Macromedia\FlashPlayer" /v "CurrentVersion"'
) DO (
REM Set "Version=%%B"
Echo Version: %%B
)
Pause&Exit
http://ss64.com/nt/for_f.html
PS: Change the reg key used if needed.
Okay here some more complex sample for the use of For /F
:: Main
#prompt -$G
call :REGQUERY "Software\Classes\CLSID\{3E6AE265-3382-A429-56D1-BB2B4D1D}"
#goto :EOF
:REGQUERY
:: Checks HKEY_LOCAL_MACHINE\ and HKEY_CURRENT_USER\
:: for the key and lists its content
#call :EXEC "REG QUERY HKCU\%~1"
#call :EXEC "REG QUERY "HKLM\%~1""
#goto :EOF
:EXEC
#set output=
#for /F "delims=" %%i in ('%~1 2^>nul') do #(
set output=%%i
)
#if not "%output%"=="" (
echo %1 -^> %output%
)
#goto :EOF
I packed it into the sub function :EXEC so all of its nasty details of implementation doesn't litters the main script.
So it got some kinda some batch tutorial.
Notes 'bout the code:
the output from the command executed via call :EXEC command is stored in %output%. Batch cmd doesn't cares about scopes so %output% will be also available in the main script.
the # the beginning is just decoration and there to suppress echoing the command line. You may delete them all and just put some #echo off at the first line is really dislike that. However like this I find debugging much more nice.
Decoration Number two is prompt -$G. It's there to make command prompt look like this ->
I use :: instead of rem
the tilde(~) in %~1 is to remove quotes from the first argument
2^>nul is there to suppress/discard stderr error output. Normally you would do it via 2>nul. Well the ^ the batch escape char is there avoids to early resolving the redirector(>). There's some simulare use a little later in the script: echo %1 -^>... so there ^ makes it possible the output a '>' via echo what else wouldn't have been possible.
even if the compare at #if not "%output%"==""looks like in most common programming languages - it's maybe different that you expected (if you're not used to MS-batch). Well remove the '#' at the beginning. Study the output. Change it tonot %output%==""-rerun and consider why this doesn't work. ;)
This is work for me
#FOR /f "delims=" %i in ('reg query hklm\SOFTWARE\Macromedia\FlashPlayer\CurrentVersion') DO set var=%i
echo %var%

CMD.EXE batch script to display last 10 lines from a txt file

Any ideas how to echo or type the last 10 lines of a txt file?
I'm running a server change log script to prompt admins to state what they're doing, so we can track changes. I'm trying to get the script to show the last 10 entries or so to give an idea of what's been happening recently. I've found a script that deals with the last line, as shown below, but can't figure out what to change in it to display the last 10 lines.
Script:
#echo off
setLocal EnableDelayedExpansion
for /f "tokens=* delims= " %%a in (c:\log09.txt) do (
set var=%%a
)
echo !var!
Example of log file:
06/02/2009, 12:22,Remote=Workstation-9,Local=,
mdb,bouncing box after updates,CAS-08754,
=================
07/02/2009, 2:38,Remote=,Local=SERVER1,
mdb,just finished ghosting c drive,CAS-08776,
=================
07/02/2009, 3:09,Remote=,Local=SERVER1,
mdb,audit of server,CAS-08776,
Any thoughts?
The script works great, just need it to pipe more lines to the screen.
Hopefully this will save Joel's eyes :)
#echo OFF
:: Get the number of lines in the file
set LINES=0
for /f "delims==" %%I in (data.txt) do (
set /a LINES=LINES+1
)
:: Print the last 10 lines (suggestion to use more courtsey of dmityugov)
set /a LINES=LINES-10
more +%LINES% < data.txt
This answer combines the best features of already existing answers, and adds a few twists.
The solution is a simple batch implementation of the tail command.
The first argument is the file name (possibly with path information - be sure to enclose in quotes if any portion of path contains spaces or other problematic characters).
The second argument is the number of lines to print.
Finally any of the standard MORE options can be appended: /E /C /P /S /Tn. (See MORE /? for more information).
Additionally the /N (no pause) option can be specified to cause the output to be printed continuosly without pausing.
The solution first uses FIND to quickly count the number of lines. The file is passed in via redirected input instead of using a filename argument in order to eliminate the printout of the filename in the FIND output.
The number of lines to skip is computed with SET /A, but then it resets the number to 0 if it is less than 0.
Finally uses MORE to print out the desired lines after skipping the unwanted lines. MORE will pause after each screen's worth of lines unless the output is redirected to a file or piped to another command. The /N option avoids the pauses by piping the MORE output to FINDSTR with a regex that matches all lines. It is important to use FINDSTR instead of FIND because FIND can truncate long lines.
:: tail.bat File Num [/N|/E|/C|/P|/S|/Tn]...
::
:: Prints the last Num lines of text file File.
::
:: The output will pause after filling the screen unless the /N option
:: is specified
::
:: The standard MORE options /E /C /P /S /Tn can be specified.
:: See MORE /? for more information
::
#echo OFF
setlocal
set file=%1
set "cnt=%~2"
shift /1
shift /1
set "options="
set "noPause="
:parseOptions
if "%~1" neq "" (
if /i "%~1" equ "/N" (set noPause=^| findstr "^") else set options=%options% %~1
shift /1
goto :parseOptions
)
for /f %%N in ('find /c /v "" ^<%file%') do set skip=%%N
set /a "skip-=%cnt%"
if %skip% lss 0 set skip=0
more +%skip% %options% %file% %noPause%
You should probably just find a good implementation of tail. But if you really really insist on using CMD batch files and want to run on any NT machine unmolested, this will work:
#echo off
setLocal EnableDelayedExpansion
for /f "tokens=* delims= " %%a in (c:\tmp\foo.txt) do (
set var9=!var8!
set var8=!var7!
set var7=!var6!
set var6=!var5!
set var5=!var4!
set var4=!var3!
set var3=!var2!
set var2=!var1!
set var1=!var!
set var=%%a
)
echo !var9!
echo !var8!
echo !var7!
echo !var6!
echo !var5!
echo !var4!
echo !var3!
echo !var2!
echo !var1!
echo !var!
There are several windows implementations of the tail command. It should be exactly what you want.
This one sounds particularly good:
http://malektips.com/xp_dos_0001.html
They range from real-time monitoring to the last x lines of the file.
Edit: I noticed that the included link is to a package It should work, but here are some more versions:
http://www.lostinthebox.com/viewtopic.php?f=5&t=3801
http://sourceforge.net/projects/tailforwin32
If file is too large it can take too long to get count of lines
another way is to use find and pass it a nowhere string
$find /v /c "%%$%!" yourtextfile.txt
this would result an output like this
$---------- yourtextfile.txt: 140
then you can parse output using for like this
$for /f "tokens=3" %i in ('find /v /c "%%$%!" tt.txt') do set countoflines=%i
then you can substract ten lines from the total lines
After trying all of the answers I found on this page none of them worked on my file with 15539 lines.
However I found the answer here to work great. Copied into this post for convenience.
#echo off
for /f %%i in ('find /v /c "" ^< C:\path\to\textfile.txt') do set /a lines=%%i
set /a startLine=%lines% - 10
more /e +%startLine% C:\path\to\textfile.txt
This code will print the last 10 lines in the "C:\path\to\textfile.txt" file.
Credit goes to OP #Peter Mortensen
using a single powershell command:
powershell -nologo "& "Get-Content -Path c:\logFile.log -Tail 10"
applies to powershell 3.0 and newer
I agree with "You should use TAIL" answer. But it does not come by default on Windows. I suggest you download the "Windows 2003 Resource Kit" It works on XP/W2003 and more.
If you don't want to install on your server, you can install the resource kit on another machine and copy only TAIL.EXE to your server. Usage is sooooo much easier.
C:\> TAIL -10 myfile.txt
Here's a utility written in pure batch that can show a lines of file within a given range.To show the last lines use (here the script is named tailhead.bat):
call tailhead.bat -file "file.txt" -begin -10
Any ideas how to echo or type the last
10 lines of a txt file?
The following 3-liner script will list the last n lines from input file. n and file name/path are passed as input arguments.
# Script last.txt
var str file, content ; var int n, count
cat $file > $content ; set count = { len -e $content } - $n
stex -e ("["+makestr(int($count))) $content
The script is in biterscripting. To use, download biterscripting from http://www.biterscripting.com , save this script as C:\Scripts\last.txt, start biterscripting, enter the following command.
script last.txt file("c:\log09.txt") n(10)
The above will list last 10 lines from file c:\log09.txt. To list last 20 lines from the same file, use the following command.
script last.txt file("c:\log09.txt") n(20)
To list last 30 lines from a different file C:\folder1\somefile.log, use the following command.
script last.txt file("C:\folder1\somefile.log") n(30)
I wrote the script in a fairly generic way, so it can be used in various ways. Feel free to translate into another scripting/batch language.

Resources