Discussion forum for all Windows batch related topics.
Moderator: DosItHelp
-
miskox
- Posts: 668
- Joined: 28 Jun 2010 03:46
#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
#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:
#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)":
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
#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
#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