I want to write a script that esentially pings another computer and gets average as number only. Right now I have a script that gets average ping as needed and shows it, but it has 'ms' prefix and I want to get rid of it. I can't seem to find cut equivalent (alright, I did found, but I can't make my existing script and it work together) that is already in Windows (it should be in cmd.exe by default).
My script:
FOR /F "usebackq skip=11 tokens=6 delims== " %i IN (`ping host2.internal`) DO #echo %i
I get: 197ms, but I need it to look like: 197.
Thanks
Replace the DO part with
DO #set FOO=%i & echo %FOO:~0,-3%
This assigns the value of %i to a temporary variable FOO so that you can then use the substring extraction capability of the shell (SET /? for explanation). I am shaving off three characters instead of two because %i includes a trailing space.
This works here in Win 8: the -4 is required for occasions where IPV6 is also in force.
FOR /F "tokens=5 delims==<ms" %i IN ('ping -4 www.google.com ^|find "Reply from"') DO #echo %i
Related
I have 324 files on a Windows 10 machine which are named in the following pattern:
[7 Numbers] [Space] [Last name] [Space] [First name]
And I need them to be:
[Last name] [Space] [First name] [Space] [7 Numbers]
I have done some quick research and found that I could write a batch script utilizing the 'rename' function:
#echo off
rename “y:\*.txt” “???-Test1.*”
However, I was unable to find out how I can program the script to take the first 7 chracters and put them to the end.
Any help is appreciated.
Given the little detail on the exact formatting of your structures, i.e what happens in the event a surname has a split like van Halen which also now contains a space:
anyway, this will cater for the situation as you've mentioned only and not for names/surnames containing spaces.
#echo off
for /f "tokens=1-3*" %%i in ('dir /b /a-d *.txt ^| findstr /R "^[1-9]"') do echo ren "%%i %%j %%k" "%%~nk %%~nj %%~ni%%~xk"
Note this example will simply echo the command and not perform the actual rename. You need to test it first before you do the renaming. Once you are happy with the result printed to console, then remove echo from the line.
Note. findstr is important here as we need to only perform the action if the file starts with numbers. You can define the findstr filter even more if you want to be more specific. Here I just focused on numbers in the beginning of any .txt file considering no name or surname should start with a number., Unless you're 50cent or some other random rapper.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
rem The following setting for the source directoryis a name
rem that I use for testing and deliberately includes 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\t w o"
FOR %%b IN ("%sourcedir%\??????? * *.txt") DO FOR /f "tokens=1*delims= " %%u IN ("%%~nb") DO SET /a junk=0&SET /a "junk=1%%u" 2>nul&IF !junk! geq 10000000 IF !junk! leq 19999999 ECHO REN "%%b" "%%v %%u.txt"
GOTO :EOF
Please note that this routine uses delayedexpansion
The first for puts the absolute filename of each file matching the mask into %%b
The second partitions the name part of the filename (%%~nb) into that part before the first space (token 1) to %%u and the remainder (token *) to %%v
junk is then set to 0 and then reset to the value of 1%%u. set /a will leave junk unchanged (therefore, 0) if %%u is not a numeric string (the 2>nul suppresses the error message) so if %%u is numeric, junk will be set to 10000000 ... 19999999.
Use !junk! to access the run-time value of junk, check it is within range and if so, echo the ren required.
Remove the echo keyword before the ren after checking the resultant report to actually rename the files.
I would like to get the path after -h option.
Are there some commands that can be helpful for this case?
Input (which is actually in my case the output of the following command - wmic process where "name like '%%w3wp%%'" get processid,commandline):
c:\windows\system32\inetsrv\w3wp.exe -ap "SharePoint Central Administration v4" -v "v4.0" -l "webengine4.dll" -a \\.\pipe\iisipm23e2eb4d-e657-4192-980c-9ac9147d2f75 -h "C:\inetpub\temp\apppools\SharePoint Central Administration v4\SharePoint Central Administration v4.config" -w "" -m 0 5144
Desired output:
"C:\inetpub\temp\apppools\SharePoint Central Administration v4\SharePoint Central Administration v4.config"
Given that the target command line does not contain wildcards * and ? as well as < and >, the following approach should do it:
At first, wrap a for /F loop around to capture the output of wmic (without ProcessID since it is anyway not used, and using option /VALUE to avoid trailing spaces), then nest another for /F that processes that text strings again (this is necessary to correctly deal with the Unicode output of wmic).
Then use a standard for loop to walk through the parts/arguments of the command line, check against -h and retrieve the subsequent (quoted or unquoted) item.
Eventually skip the remaining command line portion.
This is a possible implementation:
#echo off
rem // Capture the output of `wmic` using two `for /F` loops for proper Unicode-to-ASCII/ANSI conversion:
for /F "delims=" %%I in ('
wmic Process where "Name like '%%w3wp%%'" get CommandLine /VALUE
') do for /F "tokens=1* delims==" %%J in ("%%I") do (
rem // Reset flag, iterate through the parts of the retrieved command line:
set "FLAG=" & for %%L in (%%K) do (
rem // Check against option string `-h` (remove `/I` to become case-sensitive):
if /I "%%~K"=="-h" (
rem // Set a flag to indicate that next item is the target path:
set "FLAG=#"
) else if defined FLAG (
rem // Flag is set, hence extract unquoted target path and terminate loop:
set "TARGET=%%~K"
goto :NEXT
)
)
)
:NEXT
echo Extracted path: "%TARGET%"
Assuming this command line is in variable input:
This works on the command line, to test the approach:
for /f delims^=^"^ tokens^=1 %a in ('echo %input:*-h =%') do #echo %a
And this is your code for a batch file (reading from %input% and saving into %result%):
for /f delims^=^"^ tokens^=1 %%a in ('echo %input:*-h =%') do #set result=%%a
echo %result%
This works by first cutting everything until the -h in a variable string replacement expression and then using for /f with the " as delimiter. In order to be able to specify the " as delimiter, we can't enclose the delims=... tokens=... part in quotes as we'd normally do, instead we have to escape every individual character with special meaning (including the space) with ^.
Note: This assumes that the path will always be quoted in the command line. If it isn't, you'd need to first check if the part after cutting the left side starts with a quote and then either use the quote or the space as delimiter accordingly:
set x=%input:*-h =%
if ^%x:~0,1% equ ^" (
for /f delims^=^"^ tokens^=1 %%a in ('echo %x%') do #set result=%%a
) else (
for /f tokens^=1 %%a in ('echo %x%') do #set result=%%a
)
echo %result%
...but having to resort to this sort of unreadable trickery seriously makes me wonder whether it even makes sense to use batch files with decades of legacy for this. Did you consider using PowerShell or Python or some other proper scripting language instead?
This method assumes that the desired string ends in a quote and a space (in this case, before the -w switch).
#echo off
setlocal
set "input=c:\windows\system32\inetsrv\w3wp.exe -ap "SharePoint Central Administration v4" -v "v4.0" -l "webengine4.dll" -a \\.\pipe\iisipm23e2eb4d-e657-4192-980c-9ac9147d2f75 -h "C:\inetpub\temp\apppools\SharePoint Central Administration v4\SharePoint Central Administration v4.config" -w "" -m 0 5144"
set "x=%input:-h =" & set "part=%"
set "output=%part:" =" & REM %"
echo %output%
You may read a further explanations of the method used at this or this answers...
Just to be thorough, I'll state here my whole project and what I'm aiming at.
I intend to adapt a shell script to work in Windows cmd, as this is intended for people who are not going to have some sophisticate language available.
for g in $(curl -Ls https://api.chess.com/pub/player/hikaru/games/archives | jq -rc ".archives[]") ; do curl -Ls "$g" | jq -rc ".games[].pgn" ; done >> games.pgn
For some reason, Chess.com's API doesn't have a very important feature that Lichess' does, to export all games of a single player, so what I can do manually is to use https://api.chess.com/pub/player/hikaru/games/archives to export all available monthly archives and then hit the API for each one of them. (hikaru inside this will be a set variable, it's the nickname of the desired player to export).
The result for this command is something like
{"archives":["https://api.chess.com/pub/player/hikaru/games/2015/11","https://api.chess.com/pub/player/hikaru/games/2015/12","https://api.chess.com/pub/player/hikaru/games/2016/02","https://api.chess.com/pub/player/hikaru/games/2016/03","https://api.chess.com/pub/player/hikaru/games/2016/04","https://api.chess.com/pub/player/hikaru/games/2016/05"]}
to which I only have to append /pgn to get the desired result.
Obviously, cmd doesn't have jq available, so this involves "parsing" the string inside a batch file.
I figured if I just could replace every occurrence of " with a linebreak and echo the results, I could then use find (or findstr) to easily get a list of lines that only would need to be prefaced with curl and appended with /pgn to get my final result.
The big question is: how do I replace " with a linebreak in cmd? I found a few answers, but none of them seems to work with a special character, part of the problem is that I also didn't understand these answers enough to try and adapt them.
A second way of perhaps achieving the same result would be replacing [, ] and , with line breaks, but then I would also have to worry with deleting the final " to append /pgn, so if I'm able to do the former, it would be cleaner.
in batch/cmd, a for loop is used to process a list (separated by default delimiters like space, tab, comma). So just replace [ and ] with a space or comma, and you have a nice list to split. Finally, use find to filter the output to the relevant parts and you're done:
#Echo off
setlocal
set "string={"archives":["https://api.chess.com/pub/player/hikaru/games/2015/11","https://api.chess.com/pub/player/hikaru/games/2015/12","https://api.chess.com/pub/player/hikaru/games/2016/02","https://api.chess.com/pub/player/hikaru/games/2016/03","https://api.chess.com/pub/player/hikaru/games/2016/04","https://api.chess.com/pub/player/hikaru/games/2016/05"]}"
set "string=%string:[= %"
set "string=%string:]= %"
for %%a in (%string%) do echo %%~a|find "/"
Output:
https://api.chess.com/pub/player/hikaru/games/2015/11
https://api.chess.com/pub/player/hikaru/games/2015/12
https://api.chess.com/pub/player/hikaru/games/2016/02
https://api.chess.com/pub/player/hikaru/games/2016/03
https://api.chess.com/pub/player/hikaru/games/2016/04
https://api.chess.com/pub/player/hikaru/games/2016/05
(in case you wonder: the tilde in echo %%~a removes surrounding quotes)
Stephan's answer gave me the directions I needed to research more and build my own solution. This is not the final script to my project, but it does solve every problem presented in my original question:
#echo off
setLocal enabledelayedexpansion
for /f "delims=" %%a in (input.txt) do (
for %%b in (%%a) do (
set string=%%b
set "string=!string:[=,!"
set "string=!string:]=,!"
echo !string!>>replaced.txt
)
)
for /f "delims=" %%c in (replaced.txt) do (
for %%d in (%%c) do (
echo %%~d>>echo.txt
)
)
for /f %%e in (echo.txt) do echo curl %%~e/pgn|find ".">>list.txt
I basically run 3 sets of loops, the first one loads my input (this could not be done via set because there's a size limit, using a nested loop works around that) and replaces [ and ] for commas.
The second loop sorts again the output. This is done basically to trim unwanted characters from the first and last line.
The last loop generates a list of curl commands that will later be executed into a PGN file (which is a chess file).
This ends the scope of the question, but since my project wasn't that complex, I'll present it's final version, which improves on Compo's answer, in case someone else stumbles upon this question:
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Chess.com and Lichess API Scraper ::
:: Author: fabiorzfreitas ::
:: Extract all games from a player from Chess.com and Lichess ::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: This tool uses Chess.com and Lichess APIs to extract all games from a given player. ::
#echo off
setLocal enabledelayedexpansion
echo.
echo.
echo.
echo All input must be lowcase!
echo.
echo You can skip the input bellow by pressing Enter
echo.
echo.
echo.
set /p lichess="Input Lichess nickname and press Enter: "
set /p chess="Input Chess.com nickname and press Enter: "
echo.
:Lichess
if not defined lichess goto :Chess
curl https://lichess.org/api/games/user/%lichess% >> Games.pgn
:Chess
if not defined chess goto :End
(for /f "usebackq tokens=2 delims=[]" %%g in (`curl https://api.chess.com/pub/player/%chess%/games/archives`) do (
for %%h In (%%g) do curl "%%~h/pgn" >> Games.pgn
)
)
:End
exit
Based upon your own answer, it seems as if you could remove at least one of those steps by using the brackets [ and ], as delimiters.
You could also nest a for loop within another instead of having individual ones and writing to files.
Here it is as a single line batch-file:
#(For /F "UseBackQ Tokens=2 Delims=[]" %%G In ("input.txt") Do #For %%H In (%%G) Do #Echo curl.exe "%%~H/pgn") 1>"list.txt"
To do it directly in cmd:
(For /F "UseBackQ Tokens=2 Delims=[]" %G In ("input.txt") Do #For %H In (%G) Do #Echo curl.exe "%~H/pgn") 1>"list.txt"
I have string photo="999" price="10" category="1" . I want to get only 10. This means I need to the string which start price=" and ends with "
#For /F "Tokens=1*Delims==" %%A In ('FindStr /I "^price=" "C:\price.txt" 2^>NUL')Do #Set "Ver=%%~B"
#Echo(%%Ver%% = %Ver% & Pause
findstr always returns the complete line, if successful. So it's not the right tool for this task (actually, there is no tool in cmd at all that could do that this way).
But with a bit of logic, you can work around it: remove the part from the start until (including) the triggerword price (a task, the set command is happy to do), then process the rest with a for /f loop to get the desired substring:
set "string=photo="999" price="10" category="1""
echo check: %string%
echo debug: %string:*price=%
for /f tokens^=2^ delims^=^" %%a in ("%string:*price=%") do set "ver=%%~a"
echo ver=%ver%
If you are sure of the exact format of your string (in your example the searched substring is the second quoted argument, so the fourth token when splitted by ") it gets as easy as:
for /f tokens^=4^ delims^=^" %%a in ("%string%") do echo ver=%%~a
or
for /f tokens^=4^ delims^=^" %%a in (file.txt) do echo ver=%%~a
#ECHO OFF
SETLOCAL
set "string=photo="999" price="10" category="1""
:: remove quotes
set "string=%string:"=%"
for /f %%a in ("%string:* price=%") do set /a pricefound%%a
set pri
goto :eof
Since we don't have a representative sample of the file in question, we're forced to the conclusion that the requirement is to find the one and only appearance of price="anumber" in the file.
So, since findstr output, properly framed, would select this line, all we need do is process the string.
This is kind of a quick-and-dirty method; it may be adequate for OP's purpose.
First, remove the quotes from the string as they have a habit of interfering.
Next, use for /f in string-processing mode where it does its magic on the quoted string in parentheses. The string is the original string, minus quotes, so replace all characters up to "Spaceprice" with nothing and take the first token of the result, resulting in =10 assigned to %%a in the example case.
Then execute "set /a somevariablename=10" by simply concatenating the two strings.
Note that if the file contains a line like ... pricelastweek="9" ... then other measures may need to be taken.
Here's an example which tries to follow a similar methodology as your example code.
It uses FindStr to isolate any line in C:\price.txt, which includes the word price="<OneOrMoreDigits>". That line is saved as a variable named price, which is split under delayed expansion in a nested For loop, to remove everything up to, and including the first instance of the string price, leaving, in this case, ="10" category="1". The nested loop further splits that, to take the second token, using a doublequote character as the delimiter, (which should be your required value).
#For /F Delims^=^ EOL^= %%G In ('%__AppDir__%findstr.exe /IR "\<price=\"[0123456789]*\"\>" "C:\price.txt"') Do #(Set "price=%%G" & SetLocal EnableDelayedExpansion
For /F Tokens^=2^ Delims^=^" %%H In ("!price:* price=!") Do #EndLocal & Set "price=%%H")
#Echo %%price%% = %price% & Pause
Well clearly you need to match lines that contain price=" as there may be other lines.
What's unclear is if you need match 10 exactly, or just want that to be any number.
It seems likely you just want to match any number and grab it.
This is done easily with:
#For /F "Tokens=4 Delims=^= " %%A In ('
TYPE "C:\price.txt" ^| FIND /I "price="""') Do #(
Set "Ver=%%~A" & CALL SET Ver &Pause )
While is you need to match Price="10", which seems less useful, but at least one person took that meaning and your wording is a little unclear so I will add that was well:
#For /F "Tokens=4 Delims=^= " %%A In ('
TYPE "C:\price.txt" ^| FIND /I "price=""10"""') Do #(
Set "Ver=%%~A" & CALL SET Ver &Pause )
Note in all examples I left in the # symbols since I assume this is you being clever, and leaving ECHO ON and only removing the # symbols when you want to debug some specific thing you are doing.
However, in case not, it's worth pointing out that in a script it's usually easiest to place ECHO OFF at the start of the script instead of putting an # at the beginning of each statement to stop it from echoing.
Cheers! :)
I'm trying to remove the first 10 characters from multiple lines inside a text file using a batch script, then output the results to a new file. I ran across this and it got me pointed in the right direction but the final output isn't working.
Here's what I've got so far:
setLocal EnableDelayedExpansion
CSCRIPT /nologo %windir%\System32\prnport.vbs -l > c:\IPPorts.txt
type c:\IPPorts.txt | findstr IP_ > c:\IPPorts2.txt
for /f "tokens=*" %%a in (c:\IPPorts2.txt) do (set line=%%a set chars=!line:~10! > c:\IPPorts3.txt)
for /f "delims=" %%x in (c:\IPPorts3.txt) do CSCRIPT /nologo %windir%\System32\prnport.vbs -d -r %%x
The 2nd line exports a list of printer ports to a file named IPPorts.txt. The 3rd finds the lines with "IP_" in them and exports to IPPorts2.txt. The 4th line is supposed to remove unneeded text (which it isn't doing) and export to IPPorts3.txt. And the last line will take the results from IPPorts3.txt and then delete those ports.
IPPorts.txt is as follows:
Server name
Port name IP_172.20.51.11
Host address 172.20.51.11
Protocol RAW
Port number 9100
SNMP Disabled
These lines are repeated for every port, of which there are several. Since I only need the line containing the port name, IPPorts2.txt looks like this:
Port name IP_172.20.51.11
Port name IP_172.20.52.58
Port name IP_172.20.53.16
Port name IP_172.20.54.19
Port name IP_172.20.55.15-1
Port name IP_172.20.55.15
Port name IP_172.20.55.11
Where I'm having trouble is removing the "Port name " portion of the lines (the first 10 characters). I want the output to read on each line as "IP_X.X.X.X". The problem is the 3rd file is always empty.
Where am I going wrong? Any help is greatly appreciated.
EDIT:
This is further down under Endoro's answer, but I thought it might be nice to post the answer here. Here's what I changed the 4th line to:
for /f "tokens=* delims=" %%c in ('type c:\IPPorts2.txt') do (
set LINE=%%c
>> c:\IPPorts3.txt echo !LINE:~10!
)
This has corrected my problems. Thanks everyone!
try this:
(for /f "tokens=3" %%i in (IPPorts2.txt) do #echo %%i)>IPPorts3.txt
Script to get directory name out of DIR command output :
...
20/09/2014 01:23 [DIR] some1
21/09/2014 02:34 [DIR] some2
22/09/2014 03:45 [DIR] some3
23/09/2014 11:22 [DIR] some4
...
We want it to be:
some1
some2
some3
some4
...
Code :
#FOR /f "tokens=4" %%D IN (i:\test.txt) DO #( echo %%D ) >> result.txt
In your case tokens=3, not perfect but does the job with few lines manually edited in the result.
(For /f "tokens=3delims= " %%i in (ipports2.txt) do echo %%i) >ipports3.txt
should do it for you.
The paretheses are important - ensure that the file is created anew. If omitted, will only generate the last line.
Simply uses the delimiter [space] to tokenise the string on each line into token1=Port, token2=Name and sets %%i to each token3 in turn.
The following isn't really a different solution but merely a suggestion to simplify your script by reducing the number of output files.
In fact, it is possible to exclude all of them from the script, unless you need to keep them for history.
Basically, the idea is first to apply FINDSTR directly to the output of prnport.vbs:
CSCRIPT /nologo %windir%\System32\prnport.vbs -l | FINDSTR "IP_"
then apply a loop directly to the output of FINDSTR (note the single quotation marks around the piped command line, as well as the escaped |):
FOR /F "tokens=3" %%A IN (
'CSCRIPT /nologo %windir%\System32\prnport.vbs -l ^| FINDSTR "IP_"'
) DO …
and call prnport.vbs with another set of arguments in that same loop:
FOR /F "tokens=3" %%A IN (
'CSCRIPT /nologo %windir%\System32\prnport.vbs -l ^| FINDSTR "IP_"'
) DO (
CSCRIPT /nologo %windir%\System32\prnport.vbs -d -r %%A
)
The tokens option of a FOR /F loop specifies which token (or field) to take based on a specific delimiter or set of delimiters. The default set of delimiters is a space, a comma, a tab. Your Port name IP_whatever lines conveniently consist of exactly three tokens and the third one is what you are after, hence "tokens=3" in the options.
So, as you can see, no output files, the necessary value is extracted and passed to the target command in the same iteration.