how to escape findstr /r in a for loop to work in doskey - for-loop

I have this command
for /F "tokens=2 delims=:" %a in ('ipconfig ^| findstr /R "Default Gateway[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*"') do #ping -t %a
this works fine and extracts my default gateway and pings it
I would like to wrap this into a doskey macro called pig (aka ping gateway), but can not escape the findstr correctly. The doskey looks like this (^^ is needed to escape the pipe)
doskey pig = for /F "tokens=2 delims=:" %a in ('ipconfig ^^| findstr /R "Default Gateway[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*"') do #ping -t %a
With this however the doskey does not even register and findstr generates this output
FINDSTR: Cannot open do
FINDSTR: Cannot open #ping
FINDSTR: Cannot open -t
FINDSTR: Cannot open %a
I found out that escaping the last double quote allows for registering the doskey, but if I call the pig, it just outputs this:
More?
My imagination ends here and the machine just asks me for more...
I would like to have a doskey macro which looks up the gateway and pings it for me

First - It's important where you want to put your definition, on the command line or in a batch file. The syntax for the line will be different
Second - It's important to see what you get.
You should look into the defined macro with doskey /macros
If I use your sample on the command line I get:
pig=for /F "tokens=2 delims=:" %a in ('ipconfig ^
If I use it in a batch file I get:
pig=for /F "tokens=2 delims=:" a
For the command line you need to use (Three instead of two carets):
doskey pig=for /F "tokens=2 delims=:" %a in ('ipconfig ^^^| findstr /R "Default Gateway[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*"') do #ping -t %a
Inside a batch file use (The percent signs has to be doubled, too):
doskey pig=for /F "tokens=2 delims=:" %%a in ('ipconfig ^^^| findstr /R "Default Gateway[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*"') do #ping -t %%a

Related

Pipe symbol | unexpected in FOR /F loop

FOR /F "tokens=3 delims= " %i IN (query session | FINDSTR /i "console") DO set "ID=%i"
I am getting an error | was unexpected at this time.
Two very simple mistakes to avoid.
First by reading For /? use 'single quotes' for commands.
Secondly ^escape the |
FOR /F "tokens=3 delims= " %i IN ('query session ^| FINDSTR /i "console"') DO set "ID=%i"
Reminder as mentioned by #aschipfl in comment use doubled %% for both of your i's in a batch file or file.cmd
You should always read the usage information for a command utility before you use it. Had you done so, you would have noted that as you are specifically trying to isolate a line with the session name console, you could have used query session console instead of the less robust query session | FINDSTR /i "console". Of course, using the more appropriate command would mean that you do not have any issue with a horizontal bar, (pipe).
If you wanted, you could also skip the first, (header), line, and if you are certain, that your ID will always be the third whitespace separated token, you could then use:
From the Command Prompt, (cmd):
For /F "Skip=1 Tokens=3" %G In ('%SystemRoot%\System32\query.exe Session Console 2^>NUL') Do #Set "ID=%G"
Or from a batch file, (batch-file):
#For /F "Skip=1 Tokens=3" %%G In ('%SystemRoot%\System32\query.exe Session Console 2^>NUL') Do #Set "ID=%%G"

Quoting a long filenamed command in a for loop in a batch file

Linked:
Best free resource for learning advanced batch-file usage?
Dealing with quotes in Windows batch scripts
This appears to be one of those maddening quoting issues. In this example program:
#echo off
set wmicpath=%windir%\System32\wbem\wmic.exe
for /f "usebackq" %%a in (`%wmicpath% COMPUTERSYSTEM GET SystemType ^| findstr /I "x64"`) do (
echo %%a
)
The program runs just fine. Unless you try to quote the wmicpath. Imagine if you will that it contains a long path name. Then you should quote it. But I cannot quite get it to work. This fails:
for /f "usebackq" %%a in (`"%wmicpath%" COMPUTERSYSTEM GET SystemType ^| findstr /I "x64"`) do (
but this works!:
for /f "usebackq" %%a in (`"%wmicpath%" COMPUTERSYSTEM GET SystemType ^| findstr /I x64`) do (
as does this:
for /f "usebackq" %%a in (`"%wmicpath%" COMPUTERSYSTEM GET SystemType`) do (
There's something really odd about matching quotes in a for command. You can quote a command as long as you don't start quoting elsewhere...
Is it possible? I tried escaping at various points but I'm not sure about the escaping rules when quotes are involved...
Edit: I think this link might be the issue (ie: it's a bug): Pipe in for loop breaks double quoted variables
#echo off
setlocal enableextensions disabledelayedexpansion
set "wmicpath=%windir%\System32\wbem\wmic.exe"
for /f "usebackq delims=" %%a in (`
^""%wmicpath%" COMPUTERSYSTEM GET SystemType ^| findstr /I "x64"^"
`) do (
echo %%a
)
If you look at the start and end of the inner command, you will see two additional ^" (a escaped double quote). Your problem is that the for command is spawning a separate instance of cmd to handle the inner command, and this separate instance is removing the initial and final double quotes.
Why escaped quotes? To avoid this additional quotes being paired with the double quotes in the command that could lead to some other parsing problems.
You can run cmd /? to obtain the help page (sorry, i have a spanish locale so i will not include the output here). You will see a section about the /C and /K usage explaining quote removal behaviour.
First of all I would change the command, WMIC allows you to use a query language LIKE operator which would in this case remove the need to pipe anything.
#Echo Off
Set "WMIC=%SystemRoot%\System32\Wbem\wmic.exe"
For /F "UseBackQ Skip=1" %%a In (
`""%WMIC%" ComputerSystem Where "SystemType Like 'x64%%'" Get SystemType"`
) Do For %%b In (%%a) Do Echo=%%b
Timeout -1
Then I may even change the format of the command such that I don't use back quotes.
#Echo Off
Set "WMIC=%SystemRoot%\System32\Wbem\wmic.exe"
For /F "Skip=1" %%a In (
'""%WMIC%" ComputerSystem Where (SystemType Like "x64%%") Get SystemType"'
) Do For %%b In (%%a) Do Echo=%%b
Timeout -1
Whilst this doesn't directly answer the question in the subject title, it does allow for your particular command to work correctly.
However neither are necessary to your particular command example, because you do not need the for loop to echo that output:
#Echo Off
Set "WMIC=%SystemRoot%\System32\Wbem\wmic.exe"
"%WMIC%" ComputerSystem Get SystemType|Find /I "x64"
Timeout -1
Change Find to FindStr if you feel the need.
>x64.txt ECHO x64
for /f "usebackq" %%a in (`"%wmicpath%" COMPUTERSYSTEM GET SystemType ^| findstr /I /g:x64.txt`) do (
might be a work-around, depending on your actual application and preferences.

FOR command won't run in .cmd file, but runs at command prompt

When I try to run file.cmd containing the following:
for /l %m in (1,1,1) do #for /f "tokens=1,2* delims=:" %a in ('findstr /n /r "^" csv\data.csv ^| findstr /r "^%m:"') do #echo %b >csv\header.csv
I get this error:
" m:")'. Unexpected at this time
But when I run that same command at a command prompt (no .cmd file), it works.
You realize there is a much much much simpler way to get the first line of a file into a variable.
set /p header=<data.csv
echo %header%>header.csv

pass the output of a batch file into a for loop

I am trying to pass the output of a process into a for loop by using pipes
type %1% | findstr /R /V "Test" | for /F "tokens=*" %%i IN ('more') DO #echo %%i
but I do not know what to put in place of ('more') so that it reads the output from the findstr command. Is this even possible? Or do I have to save the output to a file and then read in the file in an entirely different batch program? Please help.
for /f "delims=" %%a in ('findstr /rv "Test" "%1%" ^| more') do echo %%a
for loops cannot read from STDIN, so you need to put the command whose output you want to process into the parantheses:
for /F "tokens=*" %%i IN ('type %1% ^| findstr /R /V "Test"') DO #echo %%i
Note that pipes must be escaped in the subshell (^|).

How to split command output in Windows command prompt?

Is there a split command in Windows, to split command output? My command is:
ipconfig | findstr /i "Default gateway" | findstr [0-9]
and the output is:
Default Gateway...: x.x.x.x
I need a single command, and the output should be only x.x.x.x.
there is not exactly a split function, but you can use FOR to accomplish what you want :
for /f "tokens=2 delims=:" %%i in ('ipconfig ^| findstr /i "Default gateway" ^| findstr [0-9]') do echo %%i
On my computer, there are two gateways returned, one for IPv4 and one for IPv6. The findstr doesn't distinguish between them. However, for me IPv4 is returned before IPv6. This batch file extracts the IP address for the gateway from the findstr output:
#echo off
setlocal ENABLEDELAYEDEXPANSION
for /f "tokens=2 delims=:" %%i in ('ipconfig ^| findstr "Default gateway"') do (
if not defined _ip set _ip=%%i
)
for /f "tokens=1 delims= " %%i in ("!_ip!") do (
set _ip=%%i
)
echo !_ip!
endlocal & set yourvar=%_ip%
I split it into two separate for commands (instead of nesting the for commands) so that I could just grab the first 'gateway' returned from the findstr. The result has a leading space, so the 2nd for command removes the leading space. The & set yourvar=%_ip% at the end is how you pass a local variable outside of the local block, but you don't have to use that...

Resources