Need find command solution for ms-dos application? - dos

I have some *.bat file containing find command to extract some particular line.
for example, if my input text file contains something like:
Login time : XX:XX
username - XXXXXX
Login time : YY:YY
username - YYYYYYY
using username lest say:
find /I "XXXXXX" input.txt | find /I "XXXXXX" > output.txt
I am able to get the username but not sure how to get the correct login time for only the searched user name?

find (and findstr) can't process line feeds. They handle each line on its own. So you have to write a script that remembers the last line, checks the current line for the searchstring and prints both the last line and the current line, if the searchstring is found.
I used findstr instead of find, because it's more secure (find "XXXXXX" would also find XXXXXXY). See findstr /? for the switches i, x and c.
#echo off
setlocal enabledelayedexpansion
set "search=xxxxxx"
for /f "delims=" %%a in (t.txt) do (
echo %%a|findstr /ixc:"username - %search%" >nul && echo !lastline! %%a
set "lastline=%%a"
)

Supposing you are actually working on windows (cmd.exe) rather than on dos (COMMAND.COM), you could use findstr, which allows to define a multi-line search string, although it only returns the first line in case of a match, but the next one is is always the same anyway, so it might not be needed.
This Windows batch-file shows what I mean:
#echo off
rem // Get Carriage-Return (CR) character:
for /F %%C in ('copy /Z "%~f0" nul') do set "CR=%%C"
rem // Get Line-Feed (LF) character:
(set LF=^
%= blank line =%
)
rem // Enable delayed expansion to be able to use CR and LF:
setlocal EnableDelayedExpansion
rem /* Specify a multi-line search string, which must literally reflect the actual
rem line-break (that is CR + LF for a DOS/Windows text file); `findstr` returns
rem only the first line when it encounters a match: */
findstr /I /R /C:"!CR!!LF!username - XXXXXX$" "input.txt" > "output.txt"
rem /* This is needed to get the second line of the multi-line match too
rem (replace this by the commented out line in case you expect multiple entries for
rem the searched user, because you would get multiple equal user name entries; the
rem commented out line ensures that there is a single user name entry at the end): */
findstr /I /R /C:"^username - XXXXXX$" "input.txt" >> "output.txt"
rem findstr /I /R /C:"^username - XXXXXX$" "input.txt" | findstr /I /R /V /C:"!CR!!LF!username" >> "output.txt"
N. B.:
I guess you are using two find commands to get rid of the header that the first one produces; you could however use the following instead:
rem // Input redirection `<` prevents `find` from returning a header:
find /I "XXXXXX" < "input.txt" > "output.txt"

Related

Command prompt FOR /F %%f IN ('DIR /B') fails for first result

I am using a batch file to rename all files in a folder into a numbered list. The code I use is as follow:
set /a Index=1
setlocal enabledelayedexpansion
for /f "tokens=*" %%f in ('dir /b') do (
echo %%f
echo !Index!
rename "%%f" "!Index!.*"
set /a Index+=1
pause
)
The result of the batch file is
G:\Directory A> (
echo
03.jpg
echo 1
rename "
03.jpg" "1.*"
set /a Index+=1
pause
)
03.jpg
1
The filename, directory name, or volume label syntax is incorrect.
Press any key to continue . . .
G:\Directory A> (
echo 04.jpg
echo 1
rename "04.jpg" "1.*"
set /a Index+=1
pause
)
04.jpg
1
The first result ALWAYS contains a line break at the beginning of the file name, which causes the RENAME command to fail. Can anyone tell me what is wrong with my code?
UPDATE
There is the folloging auto-run code set up in the Windows registry:
[HKEY_CURRENT_USER\Software\Microsoft\Command Processor]
"Autorun"="#chcp 65001>nul & prompt $d$s$s$t$_$p$g & cls"
After digging a bit with my batch file, I recognized that this is a problem with the Autorun option that I had set ages ago in Registry that look like this:
[HKEY_CURRENT_USER\Software\Microsoft\Command Processor]
"Autorun"="#chcp 65001>nul & prompt $d$s$s$t$_$p$g & cls"
Apparently the CLS command caused the weird line break to happen. After removing the CLS part from Autorun, the batch file works as it is intended to.
The finding described in the self-answer is very interesting albeit tremendously nasty!
The auto-run code contains the cls command, which sends a single form-feed character (FF, code0x0C) to the console that tells it to clear the screen (the character can be displayed by running cls > con in the console).
When executing cls within a for /F loop, the FF is captured: for /F %F in ('cls') do #echo/%F in the command prompt displays that character.
A for /F loop initiates a new cmd.exe instance to execute the given command line; this is done by preceding cmd /C to the command line.
With auto-run commands set up, they become executed within the for /F loop (due to the unfortunate lack of the /D option, which would prevent them to run).
The auto-run command line from the question has got cls involved, so for /F %F in ('rem') do #echo/%F captures a FF, even though the actual command rem does not return anything.
There are methods to suppress the FF character (note that the following code examples are intended to be placed in a batch-file rather than entered into the console):
Precede the desired command line by echo/& to append a line-break to a potential FF to have an extra line at the beginning and skip that line by for /F:
rem // Precede the desired command with `echo/` and skip the first line:
for /F "skip=1 delims=" %%I in ('echo/^& dir /B') do echo "%%I"
Retrieve a FF first and define it as the eol (end of line) character for for /F, then again prefix the desired command line with echo/& just like before:
rem // Retrieve the form-feed character and ignore lines beginning with a form-feed:
for /F delims^=^ eol^= %%F in ('echo/^& cls') do set "_FF=%%F"
rem // Precede the desired command with `echo/` and use form-feed as `eol` character:
for /F "delims= eol=%_FF%" %%I in ('echo/^& dir /B') do echo "%%I"
A more complex way needs to be gone when the auto-run code may write several arbitrary lines (that may even be empty). For this the number of said lines needs to be determined in order to become able to skip that number of lines later:
rem /* Determine the number of lines that the `AutoRun` code regurgitates, including empty ones;
rem the command line actually executed by `for /F` implicitly using `cmd /C` is as follows:
rem `chcp 437 > nul & echo/& cmd /C echo/| find /C /V ""`
rem this first returns a line-break, to have potential `AutoRun` text separated from the rest;
rem then another `AutoRun` text again with a terminal line-break is generated, but this time
rem piped into `find /C /V ""` in order to count the number of lines;
rem `chcp 437 > nul` is necessary to set the code page for the implicit `cmd.exe` instance,
rem because `find` (just like `more`) may have issues with some particulay Unicode code pages
rem (like 65001, which may be set by the `AutoRun` code): */
for /F %%C in ('chcp 437 ^> nul ^& echo/^& cmd /C echo/^| find /C /V ""') do set /A "SKIP=%%C" 2> nul
if %SKIP% gtr 0 (set "SKIP=skip=%SKIP%") else set "SKIP="
rem // Precede the desired command with `echo/` and skip as many lines as necessary:
for /F "%SKIP% delims=" %%I in ('echo/^& dir /B') do echo "%%I"

Find and replace text into txt with batch language

I have a problem with the code ...
I have the files t1.txt and t2.txt. The goal is to move from file 1 to file 2 with the same content unless it contains a specific word, in which case, the entire line must be replaced by a predefined one.
specifically I have problems with the 'if' and with the reassignment of the variable.
#echo off
setlocal enabledelayedexpansion
set p1=t1.txt
set p2=t2.txt
for /f "tokens=*" %%a in (%p1%) do (
set nl=%%a
if not "%n1%"=="%n1:texto=%" (
set n1=replace with this text
)
echo !n1! >> %p2%
)
pause>nul
exit
Your task is possible with pure batch scripting, but it is not that trivial when you want it in a safe manner, with respect to certain special characters and to not lose empty lines of the original file. So here is a way:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_IFILE=t1.txt" & rem // (input file to be processed)
set "_OFILE=t2.txt" & rem // (output file to be returned)
set "_WORD=\<texto\>" & rem // (string to search in lines, `findstr` regular expression)
set "_REPL=replace with this text" & rem // (text to replace lines containing the word)
rem // Output to console if no output file is provided:
if not defined _OFILE set "_OFILE=con"
rem /* Initialise a loop counter which should be synchronous to the line number, unless
rem a line matches the search string, so it becomes skipped and the numbers differ: */
set /A "LCNT=0"
rem // Write to output file:
> "%_OFILE%" (
rem /* Read from input file, prefix every line by a line number + `:`, skip lines
rem matching the search string: */
for /F delims^=^ eol^= %%L in ('cmd /V /C findstr /V /N /R /C:"!_WORD!" "!_IFILE!"') do (
rem // Split off the line number from the line string:
for /F "delims=:" %%K in ("%%L") do (
rem // Increment loop counter:
set /A "LCNT+=1"
rem // Store current line (including line number prefix):
set "LINE=%%L"
rem // Toggle delayed expansion in order to avoid trouble with `!`:
setlocal EnableDelayedExpansion
rem // Check whether loop counter and line number differ:
if !LCNT! lss %%K (
rem /* Numbers differ, hence return the replace line as many times
rem as the difference is: */
set /A "DIFF=%%K-LCNT"
for /L %%D in (1,1,!DIFF!) do echo(!_REPL!
)
rem // Return line with line number prefix removed:
echo(!LINE:*:=!
endlocal
rem // Synchronise loop counter with line number:
set "LCNT=%%K"
)
)
)
endlocal
exit /B
Restrictions:
lines must not exceed a length of about 8190 characters (limited by for /F and variable lengths);
the search expression must not be longer than 254 characters (limited by findstr);
the input text file must be ASCII/ANSI-encoded (cmd might handle other files wrongly, depending on the current code page);
the input text file should not contain characters with a code above 0x7F (cmd might change such characters to others, depending on the current code page);
the input text file must have DOS/Windows-style line endings (Unix-style line endings are understood, but the output text file is going to have DOS/Windows-style line endings then; MAC-style line endings are not supported at all);
The command FOR always ignores empty lines and by default it ignores also lines starting with a semicolon. On usage of delayed expansion also lines containing an exclamation mark are modified on execution of command line set nl=%%a in the loop. So a solution using FOR could be the completely wrong attempt depending on content of file t1.txt.
Download JREPL.BAT written by Dave Benham which is a batch file / JScript hybrid to run a regular expression replace on a file using JScript and store it in same directory as the batch file below.
#echo off
if not exist "%~dp0jrepl.bat" goto :EOF
if not exist "t1.txt" goto :EOF
call "%~dp0jrepl.bat" "^.*textto.*$" "replace with this text" /F "t1.txt" /O "t2.txt"
rem Compare the two files binary with ignoring the differences. Delete file
rem t1.txt if a line was modified by JREPL.BAT. Otherwise move file t1.txt
rem over t2.txt to keep the last modification date of file t1.txt for t2.txt.
%SystemRoot%\System32\fc.exe /B "t1.txt" "t2.txt" >nul
if errorlevel 1 ( del "t1.txt" ) else move /Y "t1.txt" "t2.txt"
jrepl.bat searches with a regular expression for lines containing textto and replaces all such lines by replace with this text. All other lines are copied unmodified from input file t1.txt to output file t2.txt.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
del /?
echo /?
fc /?
goto /?
if /?
move /?
rem /?
jrepl.bat /?

Find a line in a file and replace the next line

Using a .bat script, I want to find a line that says # Site 1 and replace the text in the next line with a variable. I found tutorials on StackOverflow for finding and replacing a line, but not finding a line and replacing the next line. Any help?
#echo off
set "the_file=C:\someFile"
set "search_for=somestring"
set "variable=http://site1"
for /f "tokens=1 delims=:" %%# in ('findstr /n /c:"%search_for%" "%the_file%"') do (
set "line=%%#"
goto :break
)
:break
set /a lineBefore=line-1
set /a nextLine=line+1
break>"%temp%\empty"&&fc "%temp%\empty" "%the_file%" /lb %lineBefore% /t |more +4 | findstr /B /E /V "*****" >newFile
echo %variable%>>newFile
more "%the_file%" +%nextLine% 1>>newFile
echo move /y newFile "%the_file%"
Check if newFile is ok and remove the echo at the front of the last line.
you need to set the three variables at the beginning by yourself.Have on mind that more command sets spaces instead of tabs
#ECHO OFF
SETLOCAL
SET "filename=q28567045.txt"
SET "afterme=# Site 1"
SET "putme=put this line after # Site 1"
SET "skip1="
(
FOR /f "usebackqdelims=" %%a IN ("%filename%") DO (
IF DEFINED skip1 (ECHO(%putme%) ELSE (ECHO(%%a)
SET "skip1="
IF /i "%%a"=="%afterme%" SET skip1=y
)
)>newfile.txt
GOTO :EOF
Produces newfile.txt
The flag `skip1 to skip the line is first reset, then the file is read line by line.
If the skip1 flag is set, then the replacement line is echoed in place of the line read; if not, the line read is echoed.
Then the skip1 flag is cleared
If the line read to %%a matches the string assigned to afterme then the flag skip1 is set (to y - but it doesn't matter what the value is)
Note that empty lines and those starting ; will be ignored and not reproduced - this is standard behaviour of for /f.
If you want to replce the starting file, then simply add
move /y newfile.txt "%filename%"
before the goto :eof line.
Even though I enjoy working with batch, I generally avoid using pure native batch to edit text files because a robust solution is usually complicated and slow.
This can be done easily and efficiently using JREPL.BAT - a hybrid JScript/batch utility that performs regular expression replacement. JREPL.BAT is pure script that runs natively on any Windows machine from XP onward.
#echo off
setlocal
set "newVal=Replacement value"
call jrepl "^.*" "%newValue%" /jbeg "skip=true" /jendln "skip=($txt!='# Site 1')" /f test.txt /o -
The /F option specifies the file to process
The /O option with value of - specifies to replace the original file with the result.
The /JBEG option initializes the command to skip (not replace) each line.
The /JENDLN option checks the value of each line just before it is written out, and sets SKIP off (false) if it matches # Site 1. The next line will be replaced only when SKIP is false.
The search string matches an entire line.
The replacement string is your value stored in a variable.
This problem is similar to this one and may use an equivalent solution. The pure Batch file solution below should be the fastest one of its kind.
#echo off
setlocal EnableDelayedExpansion
set "search=# Site 1"
set "nextLine=Text that replaces next line"
rem Get the line number of the search line
for /F "delims=:" %%a in ('findstr /N /C:"%search%" input.txt') do set /A "numLines=%%a-1"
rem Open a code block to read-input-file/create-output-file
< input.txt (
rem Read the first line
set /P "line="
rem Copy numLines-1 lines
for /L %%i in (1,1,%numLines%) do set /P "line=!line!" & echo/
rem Replace the next line
echo %nextLine%
rem Copy the rest of lines
findstr "^"
) > output.txt
rem Replace input file with created output file
move /Y output.txt input.txt > NUL
This method will fail if the input file have empty lines and also have other limitations.
For a further description of this method, see this post.

Nesting for loop in batch file

I want to nest a for loop inside a batch file to delete carriage return.
I tried it like you can see below but it does not work.
#echo off
setLocal EnableDelayedExpansion
for /f "tokens=* delims= " %%a in (Listfile.txt) do (
set /a N+=1
set v!N!=%%a
)
for /l %%i in (1, 1, %N%) do (
echo !v%%i!
for /r "tokens=* delims=" %%i in (windows.cpp) do (
echo %%i >> Linux11.cpp
)
)
pause
Here I want to check with windows.cpp. If its working I like to change windows .cpp with !v%%i!
You cannot do this in a batch file. You have no way of addressing or writing arbitrary characters. Every tool on Windows normally makes sure to output Windows line breaks (i.e. CR+LF). Some can read Unix-style line breaks just fine, which is why you can easily convert from them. But to them isn't possible.
Also as a word of caution: Source code files often contain blank lines (at least mine do) that are for readability. for /f skips empty lines which is why you're mangling the files for your human readers there. Please don't do that.
As for your question: When nesting two loops you have to make sure that they don't use the same loop variable. Show me a language where code like you wrote actually works.
Something like
for /l %%i in (1, 1, %N%) do (
echo !v%%i!
for /f "tokens=* delims=" %%l in ("!v%%i!") do (
rem do whatever you want to do with the lines
)
)
should probably work better (you missed the final closing parenthesis as well). Thing to remember: If you want to use a certain variable instead of a fixed file name it surely helps replacing that fixed file name by that variable.
It would be probably easiest to use some unix2dos/dos2unix converter to do that or some win32 flavor of sed.
The intrinsic issue of your code is already addressed by another answer, hence I am going to focus on the main task you are trying to accomplish, namely converting DOS/Windows-style end-of-line markers (or line-breaks) to Unix-style ones.
Doing this is very tricky in a batch file, but give the following script a try. Supposing it is called convert.bat, and the original text file is named convert.txt, run the script using the following command line:
convert.bat "convert.txt" LF
The name of the returned file will get the original file name with _converted_EOL appended. The second argument LF specifies Unix-style line-breaks; omitting it will return DOS/Windows-style ones.
So here is the code:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem check whether or not an existing file is given as the first argument
>&2 (
if "%~1"=="" (
echo No file specified.
exit /B 2
) else if not exist "%~1" (
echo File "%~1" not found.
exit /B 1
)
)
rem get carriage-return character
for /F %%A in ('copy /Z "%~0" nul') do set "CR=%%A"
rem get line-feed character (the two empty lines afterwards are mandatory!)
(set ^"LF=^
%= blank line =%
^")
rem check which line-break is given by the second argument
rem (`CR` - carriage return (Mac); `LF` - line feed (Unix);
rem anything else or nothing - CR+LF (Windows, default))
setlocal EnableDelayedexpansion
set "BR=!CR!!LF!"
if /I "%~2"=="CR" set "BR=!CR!" & (>&2 echo CR not supported.) & exit /B 3
if /I "%~2"=="LF" set "BR=!LF!"
rem convert line-breaks; append `_converted_EOL` to file name
setlocal DisableDelayedExpansion
> "%~n1_converted_EOL%~x1" (
for /F delims^=^ eol^= %%L in ('
findstr /N /R "^" "%~1"
') do (
set "LINE=%%L"
rem firstly, precede every line with a dummy character (`:`) and
rem append the specified line-break in order to avoid the loss of
rem leading white-spaces or trouble with leading equal-to signs,
rem all caused by `set /P`, which is needed here to return the
rem line without a trailing DOS/Windows-style line-break (opposed
rem to `echo`); then, let `pause` strip off that character;
rem lastly, let `findstr` return the remainder;
rem (the `rem` suffix is just there to fix syntax highlighting)
cmd /V /C ^< nul set /P #="!LINE:*:=:!!BR!" | (> nul pause & findstr "^") & rem/ "^"
)
)
endlocal
endlocal
endlocal
exit /B
The following restrictions apply:
no line must be longer than about 8190 characters (this is a general limitation of batch files);
the file must not contain any null-bytes (well, a normal text file should not hold such, but Unicode-encoded do);
the last line of the returned file will always be terminated by a line-break, even if the respective original line is not;
And here is another solution for line-break conversions: Convert all CR to CRLF in text file using CMD

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