How to use findstr for multiple strings? - cmd

Can someone please help me with this. Is it possible to use findstr in order to find file names that contain 2 different strings, for example.
I have a folder called New Folder with 3 files called file1, file2 and file3.
file1 contains words one, two, three, four, five
file2 contains words one, three, four, five
file3 contains words two, three, four, five
How do I find the file which contains both "one" and "two", in this case file1. Is this possible to do with findstr or do I have to use grep (which I would like to avoid).
I tried running this command with CMD running in the current directory but I get blank result: findstr /s /m /c:"one" *.* | findstr /s /m /c:"two"
I also tried: for /f %a in ('findstr /s /m "one" "New Folder\*.*"') do #findstr /m "two" %a but I still get the blank result.
I do not want this as a .bat file but only as CMD command.
Please let me know if this is possible.
findstr /s /m /c:"one" *.* | findstr /s /m /c:"two"
for /f %a in ('findstr /s /m "one" "New Folder\*.*"') do #findstr /m "two"

Related

How to count findstr results

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]))

Deleting certain lines from a file using batch

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

Fix findstr to ignore matching filenames with path

I'm trying to create a list of files created yesterday.
I've got the below working without /c:"cmd /c echo #path" but I want the full path.
forfiles /s /d -1 /m *.txt /c:"cmd /c echo #path" > a.txt
forfiles /s /m *.txt /c:"cmd /c echo #path" > b.txt
FOR /f "delims=; tokens=*" %%X IN ('findstr /v /g:a.txt b.txt') DO (
echo %%X
)
What is the best way to get around the issue with using findstr with a path containing backslashes? Do I need to replace all the backslashes in the comparison files with some other symbol and then change it back later or is there an easier way to do it in the findstr line?
The findstr command checks the very first search expression and changes to regular expression mode when a meta-character is found or to literal mode otherwise, unless you explicitly predefine the mode by /L (literal) or /R (regular expression).
But findstr is a nasty beast since there are still some problems even with /L:
wrong results may be returned with multiple literal search strings, unless you specify /I to do case-insensitive searches; but this is not a problem here anyway since you are dealing with directory and file names, which are treated case-insensitively by Windows anyway;
although in literal mode, escaping of meta-characters like ., [, ], ^, $, \, * and ? still occurs when there is a \ in front; you could just double all \ to work around that;
So the following code should work in most situations; delayed expansion is enabled herein by cmd /V, which is required to read the interim variable FILE that is written and read in the same command line:
forfiles /S /M "*.txt" /D -1 /C "cmd /C if #isdir==FALSE (set FILE=#path) & cmd /V /C echo(!FILE:\=\\!" > "exclude.txt"
forfiles /S /M "*.txt" /C "cmd /C if #isdir==FALSE echo #path" > "all.txt"
for /F "delims=" %%X in ('findstr /V /L /I /X /G:"exclude.txt" "all.txt"') do (
echo(%%X
)
I inserted if #isdir==FALSE here to not match directories whose names end in .txt. Also I added /X to findstr in order to match whole lines/paths only.
Regard that literal findstr search strings are limited to a length of 511 bytes (after doubling \), which can easily be reached with file paths.
However, what about a different approach that avoids findstr at all?
Here is a post I once provided for returning items newer than a relative date with forfiles: FORFILES date -after- (date calc in cmd file).
I prefer powershell for such tasks:
Get-ChildItem -Path "C:\Users\tivrick" -Recurse -ErrorAction SilentlyContinue | Where-Object { -Not $_.PSIsContainer -And $_.CreationTime.Date -Eq (Get-Date).Date.AddDays(-1) } | Select-Object -ExpandProperty FullName
If you really need to run that from a batch-file:
#PowerShell -NoP "GCI "C:\Users\tivrick" -R -EA SilentlyContinue|?{!$_.PSIsContainer -And $_.CreationTime.Date -Eq (Get-Date).Date.AddDays(-1)}|Select -Exp FullName"

List files at 2 directories and compare

I search for duplicates in two folders. Therefor I use Windows "cmd". I want to list all files and folders which are located beneath 2 different folders. The list of files are written to two textfiles. Then I want to compare the results which are listed inside the two textfiles.
My goal is to get a list of duplicate files or folders by comparing the textfile-lists.
So far I have some commands which are helpful (but the job is not done perfectly):
forfiles /p F:\firstfolder-01 /S /M *.* /C "cmd /c echo #file #fsize #fdate #ftime" >> filelist-01.txt
forfiles /p F:\secondfolder-02 /S /M *.* /C "cmd /c echo #file #fsize #fdate #ftime" >> filelist-02.txt
fc filelist-01.txt filelist-02.txt > dublicate-results.txt
Use the findstr command to get the duplicate lines:
findstr /LIXG:"filelist-01.txt" "filelist-02.txt"
To write the output to another file, use output redirection (>):
findstr /LIXG:"filelist-01.txt" "filelist-02.txt" > "filelist-dups.txt"

windows batch list any file type X in any sub dir named Y (to textfile)

I know I can get any file by type in a directory tree with
dir /s /b *.ext > list.txt
or any subdirectory by name with
dir /s/b *directoryName* >list.txt
but how do I combine this to get a list of files by type AND sub-directory name?
dir /s /b *directoryname\*.ext
>>The filename, directory name, or volume label syntax is incorrect.
I may have understood but cant you just do:
dir /s /b "SubfolderName\*.ext"
?
If you want full recursion you can use findstr to whittle away what you don't need from a full dir /b /s.
dir /s /b | findstr /i "directoryname.*\.ext$" >list.txt
... will match .ext files in any directory containing directoryname (including directoryname01 or 01 - directoryname), where the directory may be more than one level deep from the current directory.
In the findstr search regexp, the .* after directoryname signifies 0 or more of any character. In glob syntax it's like *directoryname*.ext. See help findstr for more info on findstr syntax.
dir /s /b /a-d *.ext|findstr /i /r ".*\\.*dirname.*\\.*"
The /a-d suppresses directorynames matching the .ext mask - filenames only.
The /r on the findstr is probably superfluous, as regex is default
The /i forces case-insentitivity
The string-to-match is
[any number of any characters]\[any number of any characters][directoryname][any number of any characters]\[any number of any characters]
since \ escapes \
read HELP FOR and try this in a command line
for /D %a in (dirname*) do #dir /s /b %a*.ext
for /R /D %a in (dirname*) do #dir /s /b %a\*.ext 1>>list.txt 2>nul

Resources