Multiple FINDSTRs without temporary files?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
miskox
Posts: 668
Joined: 28 Jun 2010 03:46

Multiple FINDSTRs without temporary files?

#1 Post by miskox » 23 Dec 2014 12:45

Squashman says here (viewtopic.php?p=38850#p38850) that the finding process could be optimized.

Squashman wrote:Sounds like you are slowing down your process by using extra FINDSTR commands and all those temp files.


I have a searching code similar to this:
findAND.cmd

Code: Select all

@echo off
if exist in_file.txt copy /y in_file.txt hits.tmp>nul
if exist finds.tmp del finds.tmp>nul
:0
if p%1 == p goto :1
findstr /L /I /C:%1 hits.tmp >finds.tmp
move /y finds.tmp hits.tmp
shift && goto 0
:1
for %%Z in (hits.tmp) do set len=%%~zZ
if     %len%==0 echo No matches.
if not %len%==0 more /E < hits.tmp
if exist hits.tmp del hits.tmp>nul
goto :EOF


in_file.txt

Code: Select all

[ARCHIVE 1]        \Mountains\Picture1.jpg
[ARCHIVE 1]        \Mountains\Picture2.jpg
[ARCHIVE 1]        \Mountains\Picture3.jpg
[ARCHIVE 2]        \Hawaii\Picture1.jpg
[ARCHIVE 2]        \Hawaii\Picture2.jpg
[ARCHIVE 2]        \Hawaii\Picture3.jpg


findAND.cmd performs search for patterns (provided as parameters) with logical AND (all strings must be in the same record):

Code: Select all

c:\>findAND.cmd pic ha
[ARCHIVE 2]        \Hawaii\Picture1.jpg
[ARCHIVE 2]        \Hawaii\Picture2.jpg
[ARCHIVE 2]        \Hawaii\Picture3.jpg

c:\>findAND.cmd pic mou
[ARCHIVE 1]        \Mountains\Picture1.jpg
[ARCHIVE 1]        \Mountains\Picture2.jpg
[ARCHIVE 1]        \Mountains\Picture3.jpg

c:\>findAND.cmd pic sea
No matches.


Squashman and others: any ideas for optimizing the code (yes I know - there will be plenty of good solutions).

Thanks.
Saso

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Multiple FINDSTRs without temporary files?

#2 Post by penpen » 23 Dec 2014 14:00

You could reduce the temp file usage (to only one).
Instead of

Code: Select all

findAND.cmd pic ha
findAND.cmd pic mou
findAND.cmd pic sea
you could use something like this:

Code: Select all

(findstr /L /I /C:"pic" "in_file.txt" | > "hits.tmp" findstr /L /I /C:"ha") && (<"hits.tmp" more /E) || echo No matches.
(findstr /L /I /C:"pic" "in_file.txt" | > "hits.tmp" findstr /L /I /C:"mo") && (<"hits.tmp" more /E) || echo No matches.
(findstr /L /I /C:"pic" "in_file.txt" | > "hits.tmp" findstr /L /I /C:"sea") && (<"hits.tmp" more /E) || echo No matches.
del "hits.tmp"

penpen

Aacini
Expert
Posts: 1932
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Multiple FINDSTRs without temporary files?

#3 Post by Aacini » 23 Dec 2014 20:53

Interesting! findAND.bat may be very useful:

EDIT: I slightly modified the original code in order to insert "OR" terms in each "AND" part; details below.

Code: Select all

@echo off
setlocal EnableDelayedExpansion

set command=findstr /I /L %1 in_file.txt

:0
   shift
   if "%~1" equ "" goto :1
   set command=!command! ^| findstr /I /L %1
goto 0
:1
%command% > hits.tmp
for %%Z in (hits.tmp) do (
   if %%~zZ == 0 (
      echo No matches.
   ) else (
      more /E hits.tmp
   )
)
del hits.tmp
goto :EOF

Output example:

Code: Select all

C:\ findAND.bat pic ha
[ARCHIVE 2]        \Hawaii\Picture1.jpg
[ARCHIVE 2]        \Hawaii\Picture2.jpg
[ARCHIVE 2]        \Hawaii\Picture3.jpg

C:\ findAND.bat pic mou
[ARCHIVE 1]        \Mountains\Picture1.jpg
[ARCHIVE 1]        \Mountains\Picture2.jpg
[ARCHIVE 1]        \Mountains\Picture3.jpg

C:\ findAND.bat pic mou 3
[ARCHIVE 1]        \Mountains\Picture3.jpg

C:\ findAND.bat pic sea
No matches.

The modification allows to search for several terms in each AND part; for example: search for "pic AND (ha OR mou)":

Code: Select all

findAND.bat pic "ha mou"

Antonio
Last edited by Aacini on 24 Dec 2014 11:52, edited 1 time in total.

miskox
Posts: 668
Joined: 28 Jun 2010 03:46

Re: Multiple FINDSTRs without temporary files?

#4 Post by miskox » 24 Dec 2014 03:14

penpen wrote:You could reduce the temp file usage (to only one).
Instead of

Code: Select all

findAND.cmd pic ha
findAND.cmd pic mou
findAND.cmd pic sea
you could use something like this:

Code: Select all

(findstr /L /I /C:"pic" "in_file.txt" | > "hits.tmp" findstr /L /I /C:"ha") && (<"hits.tmp" more /E) || echo No matches.
(findstr /L /I /C:"pic" "in_file.txt" | > "hits.tmp" findstr /L /I /C:"mo") && (<"hits.tmp" more /E) || echo No matches.
(findstr /L /I /C:"pic" "in_file.txt" | > "hits.tmp" findstr /L /I /C:"sea") && (<"hits.tmp" more /E) || echo No matches.
del "hits.tmp"

penpen


I am sorry for not being clear enough. There are three examples of what I want to search for.

I have a list of all my archive DVDs in one .txt file (each DVD has this .txt file with this findAND.cmd in root folder) (I have a .cmd that produces something like dir/s but in a way that each file is in its own record:

Code: Select all

[ARCHIVE 2]   123456 11.11.2014     \Hawaii\Picture1.jpg
[ARCHIVE 2]     3456 11.11.2014     \Hawaii\Picture2.jpg
[ARCHIVE 2]    23456 11.11.2014     \Hawaii\Picture3.jpg


In this way if I want to find something I try to provide as many information as possible so to get the best results (and not too many needed matches).

So those three examples are separate searches.

In this way I find things very quickly. And the latest DVD has all the information from the previous DVDs too.

Saso

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Multiple FINDSTRs without temporary files?

#5 Post by penpen » 24 Dec 2014 05:45

If you don't use too many filters (resulting cmd has to be <= 8191 chars) this "findand.bat" might help you:

Code: Select all

@echo off
setlocal enableDelayedExpansion enableExtensions

set "file=in_file.txt"
set "hits=hits.tmp"
set "atom=findstr /L /I /C:"^^^!filter^^^!""
set "findand="

for %%a in (%*) do (
   set filter=%%a
   if not defined findand (
      set "findand=%atom% "!file!""
   ) else set "findand=!findand!|%atom%"
)

echo !findand!
>"!hits!" (%findand%) && (<"!hits!" more /E) || echo No matches.
del "!hits!"
endlocal
goto :eof

penpen

Post Reply