Executing a pipe line command with findstr - windows

I am trying to get the name of a file containing a particular string. The following command does that.
dir /a:-D /b | findstr /i "fileName.jar"
I'm trying to run it through a bat file using the following code.
for /F "delims=" %%a in ('dir /a:-D /b | findstr /i "fileName.jar"') do set "batToolDir=%%a"
But I am getting the below error.
| was unexpected at this time.
I need to get the name of the file containing a certain string. How can I achieve this? Any help would be much appreciated.

"below error" ??
What you need is to escape the | to tell cmd that the pipe is part of the command to be executed, not of the for. You need to do this with all redirectors.
The escape character is ^, so substitute ^| for | within the parentheses. ANy such awkwardness, try inserting ^ before the character causing the problem...

Related

Output all results of findstr to seperate txt files

Currently my code is: findstr Starfy ./List.txt > result.txt
My result.txt is
3841 - Legendary Starfy, The (USA).zip
x166 - Legendary Starfy, The (USA) (Demo) (Kiosk).zip
However, I want result 1 and result 2 to have their own seperate files, so it would look like:
result1.txt > 3841 - Legendary Starfy, The (USA).zip
result2.txt > x166 - Legendary Starfy, The (USA) (Demo) (Kiosk).zip
I'm unsure how to make this work, and would love if someone is able to help point me in the right direction.
This works:
#echo off
for /F "tokens=1* delims=:" %%a in ('findstr "Starfy" .\List.txt ^| findstr /N "^"') do >result%%a.txt echo %%b
Just pass your original results into another instance of findstr /N command that add line numbers. After that, separate the number and the line in a for /F command and output each line to its corresponding numbered file...
for /f "tokens=1,* delims=:" %%S in ('findstr /i "echo" "%~f0"^|findstr /n /i "echo" ') do ECHO %%T>"U:\moreresults\result%%S.txt"
The command quoted in parentheses finds a string (in this case, echo) ignoring case (/i) within the file "%~f0" (this batch file, which contains a heap of standard code I use for testing). This is passed to another instance of findstr, this time looking for the same string, but numbering the lines (as serialnumber:linetext).
The resultant text is tokenised using : as a separator, so %%S receives the serialnumber and %%T receives the rest of the line (token *). Then simply build the result filename using %%S and write the text part of the line to it.
The caret is used to escape the pipe so that cmd knows that the pipe is part of the command-to-be-executed, not of the for command.
Assuming that you do not already have files in the location you're outputting your results, which could alalready be named using that intended naming scheme, then something like this may suit you:
#Echo Off
SetLocal EnableExtensions EnableDelayedExpansion
Set "i=0"
For /F Delims^=^ EOL^= %%G In (
'%SystemRoot%\System32\find.exe /I "Starfy" 0^<".\List.txt" 2^>NUL'
) Do (
Set /A i += 1
1>"Result!i!.txt" Echo %%G
)
Please note that I used find.exe instead of findstr.exe simply because your example used a simple string containing a series of alphabetic only characters. Feel free to change it to '%SystemRoot%\System32\findstr.exe /LIC:"Starfy" ".\List.txt" 2^>NUL', or similar, should you require a more specialized matching mechanism.

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"

'cut' like feature for Windows batch file

It's been a while since I've done Windows batch files, and I seem to have forgotten everything. What I want to do is look for services where the path has spaces but the string isn't quoted. Boy, this would be easy with bash, but...
So, in a nutshell, I start with sc query | findstr SERVICE_NAME and dump that to a temp file. Then I read it back in to a variable with for /F "tokens=2" %%f in (temp_file) do set services=!services! %%f That gets me a variable with a space-delimited list of all services on my host. Now, in a FOR loop against that variable, I run sc qc %%s | findstr BINARY_PATH_NAME and dump THAT to a temp file. It winds up containing something like (quotes are mine to preserve all the spaces):
" BINARY_PATH_NAME : C:\Windows\system32\svchost.exe -k LocalSystemNetworkRestricted"
I've been reading and Googling and testing and trying everything, trying to wind up cutting that output at the : so I can just wind up with the path itself, and then start figuring out the abomination that must be regular expressions under Windows. But I just cannot get that string split.
You can do the following if you want the binary path for all services:
for /f "tokens=2" %%n in ('sc query ^| findstr SERVICE_NAME') do (
for /f "delims=: tokens=1*" %%r in (
'sc qc "%%~n" ^| findstr BINARY_PATH_NAME'
) do (
echo %%~s
)
)
Change echo %%~s to echo %%~n:%%~s if you want the binary path prepended with the name of the service.
Ansgar Wiechers has a good solution using SC to get the info for running services. It also demonstrates how to use the FOR /F delims option to break at the :.
Another option is to use WMIC to get the same information in a more direct manner.
If all you want is a list of binary paths for all active (running) services, then all you need is:
wmic service where "state='Running'" get pathname
If you want the list of service names as well as the binary paths:
wmic service where "state='Running'" get name, pathname
There are many more properties that can be listed. Type wmic service get /? from the command prompt to get a complete list.
If you want to get the values into variables within a batch process so that you can take action, then a FOR /F loop is used. I append the state property at the end to avoid an odd FOR /F quirk that appends an unwanted <CR> to the end of each line of WMIC output. The unwanted <CR> will be attached to the state value, which we don't care about. I also use the state with FINDSTR to weed out unwanted lines, so there is no need for the WMIC WHERE clause. In this example I simply echo the values, but obviously you could do whatever is needed with them.
for /f "tokens=2,3 delims=," %%A in (
'"wmic service get name, pathname, state /format:csv|findstr /e Running"'
) do echo %%A: %%B
Something like this?
#echo off
for /f "tokens=2 delims=: " %%a in ('sc query ^| findstr SERVICE_NAME') do (
sc qc %%a | findstr BINARY_PATH_NAME
)
pause

Batch script with for loop and pipe

I would like all the csv files in a directory which filename does not contain word "summary". Inside the command prompt I can type the following command
dir /b my_dir\*.csv | find /V "summary"
When I try to transfer the above command into a batch file I run into a problem in that the pipe command is not supported in the for loop. That is I cannot do the following
FOR /f %%A in ('dir /b my_dir\*.csv | find /V "summary"') do (
rem want to do something here
)
Can somebody shed some light to me on how to solve the problem above?
Thanks in advance!
You need to escape the | character to prevent its being interpreted at the time of parsing the loop command. Use ^ to escape it:
FOR /f "delims=" %%A in ('dir /b "my_dir\*.csv" ^| find /V "summary"') do (
rem do what you want with %%A here
)
Once escaped, the | becomes part of the '-delimited string. It is only interpreted as a special symbol when that string is parsed separately from the loop, as a "sub-command", according to the syntax. And that is done after parsing the loop.
If you get the problem that Gilbeg got "find: /V': No such file or directory" then it's most likely you have cygwin, or similar, in your path and the batch file's not using the Windows find command. If you modify your script to use the absolute path of the Windows find then the error will go away:
FOR /f "delims=" %%A in ('dir /b "my_dir\*.csv" ^| %SYSTEMROOT%\system32\find.exe /V "summary"') do (
rem want to do something here with %%A
)
You can also just embed a double-quoted string inside the single-quotes string, as in:
FOR /f "delims=" %%A in ('"dir /b my_dir\*.csv | find /I /V "summary""') do #(
ECHO Do something with "%%A"
)
have a look at the Windows PowerShell. Not that I have ever used it myself, mind.

How do you loop through each line in a text file using a windows batch file?

I would like to know how to loop through each line in a text file using a Windows batch file and process each line of text in succession.
I needed to process the entire line as a whole. Here is what I found to work.
for /F "tokens=*" %%A in (myfile.txt) do [process] %%A
The tokens keyword with an asterisk (*) will pull all text for the entire line. If you don't put in the asterisk it will only pull the first word on the line. I assume it has to do with spaces.
For Command on TechNet
If there are spaces in your file path, you need to use usebackq. For example.
for /F "usebackq tokens=*" %%A in ("my file.txt") do [process] %%A
From the Windows command line reference:
To parse a file, ignoring commented lines, type:
for /F "eol=; tokens=2,3* delims=," %i in (myfile.txt) do #echo %i %j %k
This command parses each line in Myfile.txt, ignoring lines that begin with a semicolon and passing the second and third token from each line to the FOR body (tokens are delimited by commas or spaces). The body of the FOR statement references %i to get the second token, %j to get the third token, and %k to get all of the remaining tokens.
If the file names that you supply contain spaces, use quotation marks around the text (for example, "File Name"). To use quotation marks, you must use usebackq. Otherwise, the quotation marks are interpreted as defining a literal string to parse.
By the way, you can find the command-line help file on most Windows systems at:
"C:\WINDOWS\Help\ntcmds.chm"
In a Batch File you MUST use %% instead of % : (Type help for)
for /F "tokens=1,2,3" %%i in (myfile.txt) do call :process %%i %%j %%k
goto thenextstep
:process
set VAR1=%1
set VAR2=%2
set VAR3=%3
COMMANDS TO PROCESS INFORMATION
goto :EOF
What this does:
The "do call :process %%i %%j %%k" at the end of the for command passes the information acquired in the for command from myfile.txt to the "process" 'subroutine'.
When you're using the for command in a batch program, you need to use double % signs for the variables.
The following lines pass those variables from the for command to the process 'sub routine' and allow you to process this information.
set VAR1=%1
set VAR2=%2
set VAR3=%3
I have some pretty advanced uses of this exact setup that I would be willing to share if further examples are needed. Add in your EOL or Delims as needed of course.
Improving the first "FOR /F.." answer:
What I had to do was to call execute every script listed in MyList.txt, so it worked for me:
for /F "tokens=*" %A in (MyList.txt) do CALL %A ARG1
--OR, if you wish to do it over the multiple line:
for /F "tokens=*" %A in (MuList.txt) do (
ECHO Processing %A....
CALL %A ARG1
)
Edit: The example given above is for executing FOR loop from command-prompt; from a batch-script, an extra % needs to be added, as shown below:
---START of MyScript.bat---
#echo off
for /F "tokens=*" %%A in ( MyList.TXT) do (
ECHO Processing %%A....
CALL %%A ARG1
)
#echo on
;---END of MyScript.bat---
#MrKraus's answer is instructive. Further, let me add that if you want to load a file located in the same directory as the batch file, prefix the file name with %~dp0. Here is an example:
cd /d %~dp0
for /F "tokens=*" %%A in (myfile.txt) do [process] %%A
NB:: If your file name or directory (e.g. myfile.txt in the above example) has a space (e.g. 'my file.txt' or 'c:\Program Files'), use:
for /F "tokens=*" %%A in ('type "my file.txt"') do [process] %%A
, with the type keyword calling the type program, which displays the contents of a text file. If you don't want to suffer the overhead of calling the type command you should change the directory to the text file's directory. Note that type is still required for file names with spaces.
I hope this helps someone!
The accepted answer is good, but has two limitations.
It drops empty lines and lines beginning with ;
To read lines of any content, you need the delayed expansion toggling technic.
#echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ text.txt"`) do (
set "var=%%a"
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!"
echo(!var!
ENDLOCAL
)
Findstr is used to prefix each line with the line number and a colon, so empty lines aren't empty anymore.
DelayedExpansion needs to be disabled, when accessing the %%a parameter, else exclamation marks ! and carets ^ will be lost, as they have special meanings in that mode.
But to remove the line number from the line, the delayed expansion needs to be enabled.
set "var=!var:*:=!" removes all up to the first colon (using delims=: would remove also all colons at the beginning of a line, not only the one from findstr).
The endlocal disables the delayed expansion again for the next line.
The only limitation is now the line length limit of ~8191, but there seems no way to overcome this.
Or, you may exclude the options in quotes:
FOR /F %%i IN (myfile.txt) DO ECHO %%i
Here's a bat file I wrote to execute all SQL scripts in a folder:
REM ******************************************************************
REM Runs all *.sql scripts sorted by filename in the current folder.
REM To use integrated auth change -U <user> -P <password> to -E
REM ******************************************************************
dir /B /O:n *.sql > RunSqlScripts.tmp
for /F %%A in (RunSqlScripts.tmp) do osql -S (local) -d DEFAULT_DATABASE_NAME -U USERNAME_GOES_HERE -P PASSWORD_GOES_HERE -i %%A
del RunSqlScripts.tmp
If you have an NT-family Windows (one with cmd.exe as the shell), try the FOR /F command.
The accepted anwser using cmd.exe and
for /F "tokens=*" %F in (file.txt) do whatever "%F" ...
works only for "normal" files. It fails miserably with huge files.
For big files, you may need to use Powershell and something like this:
[IO.File]::ReadLines("file.txt") | ForEach-Object { whatever "$_" }
or if you have enough memory:
foreach($line in [System.IO.File]::ReadLines("file.txt")) { whatever "$line" }
This worked for me with a 250 MB file containing over 2 million lines, where the for /F ... command got stuck after a few thousand lines.
For the differences between foreach and ForEach-Object, see Getting to Know ForEach and ForEach-Object.
(credits: Read file line by line in PowerShell )
Modded examples here to list our Rails apps on Heroku - thanks!
cmd /C "heroku list > heroku_apps.txt"
find /v "=" heroku_apps.txt | find /v ".TXT" | findstr /r /v /c:"^$" > heroku_apps_list.txt
for /F "tokens=1" %%i in (heroku_apps_list.txt) do heroku run bundle show rails --app %%i
Full code here.
To print all lines in text file from command line (with delayedExpansion):
set input="path/to/file.txt"
for /f "tokens=* delims=[" %i in ('type "%input%" ^| find /v /n ""') do (
set a=%i
set a=!a:*]=]!
echo:!a:~1!)
Works with leading whitespace, blank lines, whitespace lines.
Tested on Win 10 CMD

Resources