I have a batch file which will give the file name & number of lines in that file. It works properly for .txt files, but I am trying to check count of a .mea file, it shows incorrect count. (It shows very large count). below is the code,please suggest any corrections to read .mea file correctly:
#echo off
(
for /R %%n IN (*.*) do (
for /F "tokens=1,*" %%f in ('find /V /C "-------------" "%%n"') do (
echo %%n : %%g
)
)) >output.txt
Most likely your .mea file is a binary type file where the line terminators as understood by Find are not considered as terminators as understood by you. (…without a genuine .mea file to examine we cannot help you verify that)
I think however that you could at least further improve your code:
…single directory
#Echo Off
( For /F "Tokens=1* Delims=- " %%A In ('Find/V /C "" *.* 2^>Nul'
) Do Echo=%%A %%B)>"SomewhereElse\Output.txt"
…recursive
#Echo Off
(For /R %%A In (*) Do For /F "Tokens=1* Delims=- " %%B In (
'Find/V /C "" "%%A" 2^>Nul') Do Echo=%%B %%C)>"SomewhereElse\Output.txt"
In both cases, unless Output.txt is written to SomewhereElse, it will show up as an entry within its own content.
Related
think I'm getting things confused here.
I've got a loop that runs all files in a folder
for /f "delims=_" %%J in ('forfiles /p "%%F" /m *.ext /c "cmd /c echo #path"')
do start "program" /D "c:\program files\path\to\program" /Wait program -r %%J
%%J should represent each file if I've set this up / interpretted this correctly.
I have another loop that is looking in the xml code for each of these files and searching for a particular pattern using findstr and parsing out the Name from some tags like this:
for /f "tokens=3 delims=<>" %%a in ('findstr /n /i "<Name>ABCDir" "%%J"')
do (set name=%%a)
echo !name!
Now I thought it would be as easy as just reusing %%J in the findstr loop but it doesn't seem to be working. When I run the code, it tells me FINDSTR: Cannot open %J and then ECHO is off
I'm guessing my problem is that it was too quick and easy to try using %%J in the next loop and that the shell isn't connecting the dots between loops.
Any ideas how I can do this? Because I need the file name in the findstr loop to always match the file in the first loop.
EDIT: Here's what the file might look like.
c:\path\to\the file name
Here's what the output looks like:
FINDSTR: Cannot open "c:\path\
FINDSTR: Cannot open to\
FINDSTR: Cannot open the
FINDSTR: Cannot open file
FINDSTR: Cannot open name
so it would seem its a simple issue of how the shell is reading the %%J variable. This type of thing has shown up when I've forgotten to put quotes around file names before but the quotations are around %%J. I even tried double quotations but was a little relieved when that didn't fix it.
EDIT2: I changed
for /f "tokens=3 delims=<>" %%a in ('findstr /n /i "<Name>ABCDir" "%%J"')
do (set name=%%a)
to
for /f "tokens=3 delims=<>" %%a in ('findstr /n /i "<Name>ABCDir" "%%~nJ"')
do (set name=%%a)
and now the output is: FINDSTR: Cannot open the file name. So now at least its reading the file in full. At least it would seem that way.
for %%J in ( ... ) do (
....
%%J is visible here, inside the do clause
....
) <- here %%J goes out of scope
So, you can include your second (third : %%F?) for loop inside the do clause of the first one
for %%J in ("%%F\*.ext") do (
start "program" /D "c:\program files\path\to\program" /Wait program -r "%%~fJ"
for /f "tokens=3 delims=<>" %%a in ('findstr /n /i "<Name>ABCDir" "%%J"') do (
echo %%a
)
)
I am new here. I found the way to find only one string from a directory.
findstr /S /M /C:"string" /C:folder *.txt
I can get success for only one string. But my wish is to find a solution, where i will write my wanted multiple strings in a file and will call that file by command and write the directory or folder name, where these information can be found.
i found some information from this forum but i could not succeeded.
#echo off
set RESULT_FILE="result.txt"
set /p "var1=Enter the String to Find: "
pushd %~p0
type NUL > %RESULT_FILE%.tmp
for /f "delims=" %%a in ('dir /B /S *.txt') do (
for /f "tokens=3 delims=:" %%c in ('find /i /c "%var1%" "%%a"') do (
for /f "tokens=*" %%f in ('find /i "%var1%" "%%a"') do if %%c neq 0 echo %%f
)
) >> "%RESULT_FILE%".tmp
move %RESULT_FILE%.tmp %RESULT_FILE% >nul 2>&1
:: Open the file
"%RESULT_FILE%"
popd
this code is also not working for me... after run, i get a blank result.txt file
I hope you already experienced the same problem and can help me to get rid of that problem.
If you have any questions, please let me know. I will be happy to answer.
Thanks in advance.
findstr /r /s /m "string1 string2 string3" *.txt
Space seperates search terms.
I have a simply FOR /F loop which strips out all but one line of a text file:
for /f "skip=12 tokens=* delims= " %%f in (.\NonProcessed\*.txt) do (
> newfile.txt echo.%%f
goto :eof
)
But when I run, I get the result:
The system cannot find the file .\NonProcessed\*.txt
The for loop works fine if I enter a fully qualified path to the text file within the brackets, but it can't handle the relative link I have in there. I've been able to use the exact same relative link in another standard for loop in a different batch file running in the same directory without any issues. I can't understand why it won't work! Please help.
EDIT: For comments, code I'm using now is
for %%f in (.\NonProcessed\*.txt) do (
echo f is %%f
for /f "usebackq skip=12 tokens=* delims= " %%a in (%%f) do (
echo a is %%a
> %%f echo.%%a
goto :continue
)
:continue
sqlcmd stuff here
)
Sorry but for /f does not allow you to do that. And no, the problem is not the relative path to files but the wildcard.
According to documentation, you have the syntax case
for /F ["ParsingKeywords"] {%% | %}variable in (filenameset) do command [CommandLineOptions]
For this case, documentation states The Set argument specifies one or more file names. You can do
for /f %%a in (file1.txt file2.txt file3.txt) do ...
but wildcards are not allowed.
If you don't know the name of the file you want to process, your best option is to add an additional for command to first select the file
for %%a in (".\NonProcessed\*.txt"
) do for /f "usebackq skip=12 tokens=* delims= " %%f in ("%%~fa"
) do (
> newfile.txt echo(%%f
goto :eof
)
When executed, the goto command will cancel both for loops so you end with the same behaviour you expected from your original code.
edited to adapt code to comments
#echo off
set "folder=.\NonProcessed"
pushd "%folder%"
for /f "tokens=1,2,* delims=:" %%a in (
' findstr /n "^" *.txt ^| findstr /r /b /c:"[^:]*:13:" '
) do (
echo Overwrite file "%%a" with content "%%c"
>"%%a" echo(%%c
)
popd
Read all the files in the folder, numbering the lines. The output for the first findstr command will be
filename.txt:99:lineContents
This output is parsed to find the line 13, the resulting data is splitted using the colon as a separator, so we will end with the file name in %%a, the line number in %%b and the line content in %%c.
SET FILES_LIST=files_list.config
DIR /b .\NonProcessed\*.txt>!FILES_LIST!
for /f "skip=12 tokens=* delims= " %%f in (!FILES_LIST!) do (
> newfile.txt echo.%%f
goto :eof
)
IF EXIST "!FILES_LIST!" DEL "!FILES_LIST!"
I did not check how your's FOR works, just added my additions/corrections to it.... Hope it will work for you.
Best regards!
I am looking to find a batch or VBS solution to strip out lines in a program generated text file with the extension of .trs.
In every .trs file created there is a line that contains the word 'labour'. I need every line after the line that contains the word labour to be deleted.
The .trs files are all stored in c:\export
I have searched for this but some of the commands were well over my head. Could anyone be so kind as to offer me a cut and paste open of the whole batch file, please.
I believe this is the code you are looking for (in a batch file) to remove all of the lines above the word "labour". Let me know if modifications need to be made to the code (such as if there are more than one instance of "labour" in the file).
#echo OFF
setLocal EnableDelayedExpansion
cd C:\export
for /f "delims=" %%I in ('findstr /inc:"labour" "test.trs"') do (
set /A"line=%%I"
)
set count=0
for /f "delims=" %%A in (test.trs) do (
If !count! GEQ %line% goto ExitLoop
echo %%A >>temp.txt
set /A count+=1
echo !count!
)
:ExitLoop
type temp.txt > test.trs
del temp.txt
endlocal
OUTPUT:
test.trs (BEFORE changes)
this
is
a
labour
test
of
the
results
test.trs (AFTER changes)
this
is
a
Here is an alternate method to process every .trs file in "C:\export":
#echo off
if not exist "C:\export\*.trs" goto :EOF
if exist "C:\export\queue.tmp" del /q "C:\export\queue.tmp"
for /f "tokens=*" %%A in ('dir /b "C:\export\*.trs"') do (
for /f "tokens=1,2 delims=:" %%B in ('findstr /inc:"labour" "C:\export\%%A" ^| findstr /n .*') do if "%%B" equ "1" set LineNumber=%%C
for /f "tokens=1* delims=:" %%D in ('findstr /n .* "C:\export\%%A"') do if %%D lss %LineNumber% echo.%%E>>"C:\export\queue.tmp"
move /y "C:\export\queue.tmp" "C:\export\%%A">NUL
)
First, I do some error checking to avoid things that would break the script. Next, I pull a list of .trs files stored in C:\export, and loop through each file.
I use 'findstr /inc:"labour" "C:\export\%%A"' to get the line number where "labour" is found in the current file, then pipe it into 'findstr /n .*' to number the results in case more than one match is found.
I then use a for loop with "tokens=1,2 delims=:" to find the first result (if "%%B" equ "1") and store the line number (set LineNumber=%%C).
Next, I use 'findstr /n .* "C:\export\%%A"' to read every line of the file, "tokens=1* delims=:" to separate out the line numbers again, then copy all the data to a temp file until %LineNumber% has been reached. This method of reading the file (using findstr and numbering the lines) also ensures that no blank lines will be skipped by the for loop.
Finally, I replace the original file with the temp file, then loop through to the next file.
I tried to keep the above code as slimmed down as possible. Here is the same script with formatting, comments, visual feedback, and user-definable variables:
#echo off
::Set user-defined Variables
set FilePath=C:\export
set FileType=*.trs
set Keyword=labour
::Check for files to process and exit if none are found
if not exist "%FilePath%\%FileType%" echo Error. No files to process.&goto :EOF
::Delete temp file if one already exists
if exist "%FilePath%\queue.tmp" del /q "%FilePath%\queue.tmp"
::List all files in the above specified destination, then process them one at a time
for /f "tokens=*" %%A in ('dir /b "%FilePath%\%FileType%"') do (
::Echo the text without a line feed (so that "Done" ends up on the same line)
set /p NUL=Processing file "C:\export\%%A"... <NUL
::Search the current file for the specified keyword, and store the line number in a variable
for /f "tokens=1,2 delims=:" %%B in ('findstr /inc:"%Keyword%" "%FilePath%\%%A" ^| findstr /n .*') do (
if "%%B" equ "1" set LineNumber=%%C
)>NUL
::Output all data from the current file to a temporary file, until the line number found above has been reached
for /f "tokens=1* delims=:" %%D in ('findstr /n .* "%FilePath%\%%A"') do (
if %%D lss %LineNumber% echo.%%E>>"%FilePath%\queue.tmp"
)>NUL
::Replace the current file with the processed data from the temp file
move /y "%FilePath%\queue.tmp" "%FilePath%\%%A">NUL
echo Done.
)
This DOS batch script is stripping out the blank lines and not showing the blank lines in the file even though I am using the TYPE.exe command to convert the file to make sure the file is ASCII so that the FIND command is compatible with the file. Can anyone tell me how to make this script include blank lines?
#ECHO off
FOR /F "USEBACKQ tokens=*" %%A IN (`TYPE.exe "build.properties" ^| FIND.exe /V ""`) DO (
ECHO --%%A--
)
pause
That is the designed behavior of FOR /F - it never returns blank lines. The work around is to use FIND or FINDSTR to prefix the line with the line number. If you can guarantee no lines start with the line number delimiter, then you simply set the appropriate delimiter and keep tokens 1* but use only the 2nd token.
::preserve blank lines using FIND, assume no line starts with ]
::long lines are truncated
for /f "tokens=1* delims=]" %%A in ('type "file.txt" ^| find /n /v ""') do echo %%B
::preserve blank lines using FINDSTR, assume no line starts with :
::long lines > 8191 bytes are lost
for /f "tokens=1* delims=:" %%A in ('type "file.txt" ^| findstr /n "^"') do echo %%B
::FINDSTR variant that preserves long lines
type "file.txt" > "file.txt.tmp"
for /f "tokens=1* delims=:" %%A in ('findstr /n "^" "file.txt.tmp"') do echo %%B
del "file.txt.tmp"
I prefer FINDSTR - it is more reliable. For example, FIND can truncate long lines - FINDSTR does not as long as it reads directly from a file. FINDSTR does drop long lines when reading from stdin via pipe or redirection.
If the file may contain lines that start with the delimiter, then you need to preserve the entire line with the line number prefix, and then use search and replace to remove the line prefix. You probably want delayed expansion off when transferring the %%A to an environment variable, otherwise any ! will be corrupted. But later within the loop you need delayed expansion to do the search and replace.
::preserve blank lines using FIND, even if a line may start with ]
::long lines are truncated
for /f "delims=" %%A in ('type "file.txt" ^| find /n /v ""') do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*]=!"
echo(!ln!
endlocal
)
::preserve blank lines using FINDSTR, even if a line may start with :
::long lines >8191 bytes are truncated
for /f "delims=*" %%A in ('type "file.txt" ^| findstr /n "^"') do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*:=!"
echo(!ln!
endlocal
)
::FINDSTR variant that preserves long lines
type "file.txt" >"file.txt.tmp"
for /f "delims=*" %%A in ('findstr /n "^" "file.txt.tmp"') do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*:=!"
echo(!ln!
endlocal
)
del "file.txt.tmp"
If you don't need to worry about converting the file to ASCII, then it is more efficient to drop the pipe and let FIND or FINDSTR open the file specified as an argument, or via redirection.
There is another work around that completely bypasses FOR /F during the read process. It looks odd, but it is more efficient. There are no restrictions with using delayed expansion, but unfortunately it has other limitations.
1) lines must be terminated by <CR><LF> (this will not be a problem if you do the TYPE file conversion)
2) lines must be <= 1021 bytes long (disregarding the <CR><LF>)
3) any trailing control characters are stripped from each line.
4) it must read from a file - you can't use a pipe. So in your case you will need to use a temp file to do your to ASCII conversion.
setlocal enableDelayedExpansion
type "file.txt">"file.txt.tmp"
for /f %%N in ('find /c /v "" ^<"file.txt.tmp"') do set cnt=%%N
<"file.txt.tmp" (
for /l %%N in (1 1 %cnt%) do(
set "ln="
set /p "ln="
echo(!ln!
)
)
del "file.txt.tmp"
I wrote a very simple program that may serve as replacement for FIND and FINDSTR commands when they are used for this purpose. My program is called PIPE.COM and it just insert a blank space in empty lines, so all the lines may be directly processed by FOR command with no further adjustments (as long as the inserted space don't cares). Here it is:
#ECHO off
if not exist pipe.com call :DefinePipe
FOR /F "USEBACKQ delims=" %%A IN (`pipe ^< "build.properties"`) DO (
ECHO(--%%A--
)
pause
goto :EOF
:DefinePipe
setlocal DisableDelayedExpansion
set pipe=´)€ì!Í!ŠÐŠà€Ä!€ü.t2€ü+u!:æu8²A€ê!´#€ì!Í!².€ê!´#€ì!Í!²+€ê!´#€ì!Í!Šò€Æ!´,€ì!Í!"Àu°´LÍ!ëÒ
setlocal EnableDelayedExpansion
echo !pipe!>pipe.com
exit /B
EDIT: Addendum as answer to new comment
The code at :DefinePipe subroutine create a 88 bytes program called pipe.com, that basically do a process equivalent to this pseudo-Batch code:
set "space= "
set line=
:nextChar
rem Read just ONE character
set /PC char=
if %char% neq %NewLine% (
rem Join new char to current line
set line=%line%%char%
) else (
rem End of line detected
if defined line (
rem Show current line
echo %line%
set line=
) else (
rem Empty line: change it by one space
echo %space%
)
)
goto nextChar
This way, empty lines in the input file are changed by lines with one space, so FOR /F command not longer omit they. This works "as long as the inserted space don't cares" as I said in my answer.
Note that the pipe.com program does not work in 64-bits Windows versions.
Antonio
Output lines including blank lines
Here's a method I developed for my own use.
Save the code as a batch file say, SHOWALL.BAT and pass the source file as a command line parameter.
Output can be redirected or piped.
#echo off
for /f "tokens=1,* delims=]" %%a in ('find /n /v "" ^< "%~1"') do echo.%%ba
exit /b
EXAMPLES:
showall source.txt
showall source.txt >destination.txt
showall source.txt | FIND "string"
An oddity is the inclusion of the '^<' (redirection) as opposed to just doing the following:
for /f "tokens=1,* delims=]" %%a in ('find /n /v "" "%~1"') do echo.%%ba
By omitting the redirection, a leading blank line is output.
Thanks to dbenham, this works, although it is slightly different than his suggestion:
::preserve blank lines using FIND, no limitations
for /f "USEBACKQ delims=" %%A in (`type "file.properties" ^| find /V /N ""`) do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*]=!"
echo(!ln!
endlocal
)
As mentioned in this answer to the above question, it doesn't seem that lines are skipped by default using for /f in (at least) Windows XP (Community - Please update this answer by testing the below batch commands on your version & service pack of Windows).
EDIT: Per Jeb's comment below, it seems that the ping command, in at least Windows XP, is
causing for /f to produce <CR>'s instead of blank lines (If someone knows specifically why, would
appreciate it if they could update this answer or comment).
As a workaround, it seems that the second default delimited token (<space> / %%b in the example)
returns as blank, which worked for my situation of eliminating the blank lines by way of an "parent"
if conditional on the second token at the start of the for /f, like this:
for /f "tokens=1,2*" %%a in ('ping -n 1 google.com') do (
if not "x%%b"=="x" (
{do things with non-blank lines}
)
)
Using the below code:
#echo off
systeminfo | findstr /b /c:"OS Name" /c:"OS Version"
echo.&echo.
ping -n 1 google.com
echo.&echo.
for /f %%a in ('ping -n 1 google.com') do ( echo "%%a" )
echo.&echo.&echo --------------&echo.&echo.
find /?
echo.&echo.
for /f %%a in ('find /?') do ( echo "%%a" )
echo.&echo.
pause
.... the following is what I see on Windows XP, Windows 7 and Windows 2008, being the only three versions & service packs of Windows I have ready access to: