so I need to be able to remove certain lines from a text file based on the first word of that line.
I have tried type file.txt | findstr /v %VAR% file.txt>file.txt but that just clears the whole file.
I also tried
set /p VAR=word:
type file.txt | findstr /v %VAR% file.txt>new_file.txt
del /q file.txt
ren new_file.txt file.txt
but I still get the same problem.
Is there anyway I can do this?
Why are you using type and a pipe |, even though findstr could read the text file on its own? Simply use:
findstr /V /I "^%VAR%\>" "file.txt" > "new_file.txt"
The ^ anchors the string to the beginning of the line, and the \> constitutes a word boundary as you want to match the first word.
In case %VAR% might also contain SPACEs, which separates multiple search strings, use this to keep the whole string as one search string:
findstr /V /I /R /C:"^%VAR%\>" "file.txt" > "new_file.txt"
Remove the /I option if you want to do case-sensitive searching.
To overwrite the original file with the new one, just use:
move /Y "new_file.txt" "file.txt" > nul
Related
I use 'findstr' to find certain common values in a lot of files and I get a list of all files containing it. Is there a way to count those results so I don't have to do it manually, or like enable row numbers in CMD?
I would typically do something like:
c:\>findstr some-string file.txt > results.txt
This will pipe the command line output into a new text file named results.txt
Go to Windows Explorer. Find results.txt file.
Right-click --> Edit
Ctrl-A to select all
Look at very bottom of Notepad to see the total number of lines.
I use 'findstr' to find certain common values in a lot of files and I get a list of all files containing it.
So you probably use something like findstr /m "searchstring" *.*
Is there a way to count those results so I don't have to do it manually
yes, feed it through find, which can count:
findstr /m "searchstring" *.* | find /c /v ""
or like enable row numbers in CMD?
just for academic reasons (you already have your number):
findstr /m "searchstring" *.* | find /n /v ""
Just in case you need it as variable: use a for /f loop to catch the result:
for /f %a in ('findstr /m "searchstring" *.* ^| find /c /v ""') do set count=%a
(%a is command line syntax. Use %%a in a batch file)
Just in case Compo is right: to get the occurrences of the searchstring per file:
find /c "searchstring" *.* 2>nul
(2>0 suppresses errormessages for folders (which find tries to search, but miserably fails because they are not files [well, technically they are, but that's out of scope for your problem]))
Can someone have a look at this mess please?
I have in the file test.txt a line with the search string Coupon (%), but FINDSTR searches just for Coupon. I have tried another line with search string Coupon frequency in file test.txt which results in searching also just for Coupon.
This is the command line in the batch file:
for /f %%f in ('dir /s /b C:\Users\me\Desktop\script\links\') do for /f %%t in ('type C:\Users\me\Desktop\script\test.txt') do for /f "delims=:" %%a in ('findstr /n /c:"%%t" %%f') do C:\Users\me\Desktop\script\links2.exe %%f %%a && echo %%t
How can I make this command line to use the entire line in file test.txt as entire search string as I would expect with the FINDSTR /c: switch please?
It works fine if I use the option /g: on searching the file test.txt. But I need the search results output to be in the order in which I specified the search strings in the file test.txt and /g: outputs all lines with any of the searched strings in line order of the searched file which is why I'm using TYPE.
You need
... for /f "delims=" %%t in ...
Stands out. Your code will select the first token by default, using the default delimiters (Space or Tab) hence "Coupon". Using "delims=" selects the entire line for %%t
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"
I am using findstr to search an string in some file and redirecting the search result to another txt file but need to omit the searched file name added in results.
My batch file has :- findstr /s "TEST" subfolder/test.dat > output.txt
and the result of output.txt with the filename test.dat(which I need to remove):-
subfolder/test.dat:2014-04-15;TEST TECHNOLOGY LTD
Same kind of question has been asked here. But in my case I am not using any wildcards. Please help.
Parse the output of recursive dir:
>output.txt (
for /f "eol=* delims=" %%a in ('dir /s /b "subfolder\test.dat"') do (
findstr /c:"TEST" "%%a"
)
)
eol=* is used to correctly parse folders with ; which is treated as comment by for /f
delims= (empty) means that linebreak is used to delimit the output, so the line is taken entirely
/c: is used to indicate literal search string so that it may contain spaces
Alternatively you can strip the file names from the recursive findstr's output:
>output.txt (
for /f "delims=: tokens=1*" %%a in (
'findstr /s /c:"TEST" "subfolder\test.dat"'
) do echo.%%b
)
In case you want to specify a drive qualifier use tokens=2*.
One more way is to pipe with TYPE
If there's only one file:
type "subfolder/test.dat" |Findstr "TEST" > output.txt
The S switch is for searching in subfolders so if the files are more:
for /r "subfolder" %%a in (*.dat) do type %%~fa|Findstr "TEST" >> output.txt
I am very new to batch scripting. I don't have much knowledge about Batch Scripting.
My doubt is how to copy only some line from text file to other text file.
Say my File.txt is
This is sample file.
I want copy this line.
Also this line.
But not this line.
I want to copy line 2 and 3, but not using their line number, because may change.
This muchI have done till now:
#ECHO OFF
SET InFile=abc.txt
SET OutFile=Output.txt
IF EXIST "%OutFile%" DEL "%OutFile%"
SET TempFile=Temp.txt
IF EXIST "%TempFile%" DEL "%TempFile%"
IF EXIST "%OutFile%" DEL "%OutFile%"
FOR /F "tokens=*" %%A IN ('FINDSTR "I want" "%InFile%"') DO (
ECHO.%%A> "%TempFile%"
ECHO.%TempFile%>>"%OutFile%"
REM CALL :RemovePrecedingWordA "%%A"
)
FOR /F "tokens=*" %%A IN ('FINDSTR " Also this" "%InFile%"') DO (
ECHO.%%A> "%TempFile%"
ECHO.%TempFile%>>"%OutFile%"
REM CALL :RemovePrecedingWordA "%%A"
)
But its not working. Please help.
You could use the /g: option to findstr, basically do
findstr /g:pattern.txt %InFile% > %OutFile%
where pattern.txt is (in your example)
I want
Also this
This assumes you can write findstr regular expressions for all the lines you want to copy.
If you use findstr with multiple files (wildcard) you will get the file name prepended. To get round this, use
del out.txt
for %F in (*.txt); do findstr /g:pattern.txt %F >> out.txt
Note that you should put the source files in a different directory to the pattern and output files (or use a different extension) otherwise the *.txt wildcard will pick those files up, too.
You can also use sed for this purpose. Certain lines (in this case 2 and 3) are copied as follows:
sed -n -e 2p -e 3p input.txt > output.txt
If you wish to copy a segment of lines (all lines from line 2 to line 10) then you may use:
sed -n -e 2,10p input.txt > output.txt
Or you can also use combinations of certain lines and segments:
sed -n -e 2,10p -e 15p -e 27p input.txt > output.txt