ADD: Find Files: Option to exclude subdirectories and files from search.

This commit is contained in:
cobines 2012-04-16 09:28:58 +00:00
commit 4b833bbd56
7 changed files with 287 additions and 144 deletions

View file

@ -1,11 +1,11 @@
object frmFindDlg: TfrmFindDlg
Left = 95
Height = 528
Height = 552
Top = 64
Width = 846
Width = 835
Caption = 'Find files'
ClientHeight = 528
ClientWidth = 846
ClientHeight = 552
ClientWidth = 835
Constraints.MinHeight = 360
Constraints.MinWidth = 585
KeyPreview = True
@ -21,20 +21,20 @@ object frmFindDlg: TfrmFindDlg
LCLVersion = '0.9.30.5'
object pnlFindFile: TPanel
Left = 3
Height = 522
Height = 546
Top = 3
Width = 840
Width = 829
Align = alClient
BorderSpacing.Around = 3
BevelOuter = bvNone
ClientHeight = 522
ClientWidth = 840
ClientHeight = 546
ClientWidth = 829
TabOrder = 0
object pgcSearch: TPageControl
Left = 0
Height = 522
Height = 546
Top = 0
Width = 722
Width = 711
ActivePage = tsStandard
Align = alClient
TabIndex = 0
@ -43,8 +43,8 @@ object frmFindDlg: TfrmFindDlg
Caption = 'Standard'
ChildSizing.LeftRightSpacing = 3
ChildSizing.TopBottomSpacing = 3
ClientHeight = 488
ClientWidth = 714
ClientHeight = 512
ClientWidth = 703
object lblFindPathStart: TLabel
AnchorSideLeft.Control = tsStandard
AnchorSideTop.Control = tsStandard
@ -56,13 +56,58 @@ object frmFindDlg: TfrmFindDlg
FocusControl = edtFindPathStart
ParentColor = False
end
object lblFindFileMask: TLabel
AnchorSideLeft.Control = tsStandard
object edtFindPathStart: TDirectoryEdit
AnchorSideLeft.Control = lblFindPathStart
AnchorSideTop.Control = lblFindPathStart
AnchorSideTop.Side = asrBottom
AnchorSideRight.Side = asrBottom
Left = 3
Height = 29
Top = 25
Width = 675
ShowHidden = False
ButtonWidth = 23
NumGlyphs = 1
Anchors = [akTop, akLeft, akRight]
MaxLength = 0
TabOrder = 0
end
object lblExcludeDirectories: TLabel
AnchorSideLeft.Control = cmbFindFileMask
AnchorSideTop.Control = edtFindPathStart
AnchorSideTop.Side = asrBottom
Left = 3
Height = 22
Top = 57
Width = 153
BorderSpacing.Top = 3
Caption = '&Exclude subdirectories'
ParentColor = False
end
object cmbExcludeDirectories: TComboBox
AnchorSideLeft.Control = tsStandard
AnchorSideTop.Control = lblExcludeDirectories
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = tsStandard
AnchorSideRight.Side = asrBottom
Left = 3
Height = 29
Hint = 'Enter directories names that should be excluded from search separated with ";"'
Top = 79
Width = 697
Anchors = [akTop, akLeft, akRight]
ItemHeight = 21
ParentShowHint = False
ShowHint = True
TabOrder = 1
end
object lblFindFileMask: TLabel
AnchorSideLeft.Control = tsStandard
AnchorSideTop.Control = cmbExcludeDirectories
AnchorSideTop.Side = asrBottom
Left = 3
Height = 22
Top = 111
Width = 74
BorderSpacing.Top = 3
Caption = '&File mask'
@ -79,13 +124,45 @@ object frmFindDlg: TfrmFindDlg
AnchorSideRight.Side = asrBottom
Left = 3
Height = 29
Top = 79
Width = 708
Hint = 'Enter files names separated with ";"'
Top = 133
Width = 697
Anchors = [akTop, akLeft, akRight]
ItemHeight = 21
TabOrder = 0
ParentShowHint = False
ShowHint = True
TabOrder = 2
Text = '*'
end
object lblExcludeFiles: TLabel
AnchorSideLeft.Control = cmbFindFileMask
AnchorSideTop.Control = cmbFindFileMask
AnchorSideTop.Side = asrBottom
Left = 3
Height = 22
Top = 165
Width = 86
BorderSpacing.Top = 3
Caption = 'E&xclude files'
ParentColor = False
end
object cmbExcludeFiles: TComboBox
AnchorSideLeft.Control = tsStandard
AnchorSideTop.Control = lblExcludeFiles
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = tsStandard
AnchorSideRight.Side = asrBottom
Left = 3
Height = 29
Hint = 'Enter files names that should be excluded from search separated with ";"'
Top = 187
Width = 697
Anchors = [akTop, akLeft, akRight]
ItemHeight = 21
ParentShowHint = False
ShowHint = True
TabOrder = 3
end
object gbFindData: TGroupBox
AnchorSideTop.Control = gbFindOptions
AnchorSideTop.Side = asrBottom
@ -93,16 +170,16 @@ object frmFindDlg: TfrmFindDlg
AnchorSideRight.Side = asrBottom
Left = 3
Height = 151
Top = 235
Width = 708
Top = 343
Width = 697
Anchors = [akTop, akLeft, akRight]
AutoSize = True
BorderSpacing.Top = 3
Caption = 'Find Data'
ChildSizing.TopBottomSpacing = 2
ClientHeight = 129
ClientWidth = 704
TabOrder = 2
ClientWidth = 693
TabOrder = 5
object lblEncoding: TLabel
AnchorSideLeft.Control = gbFindData
AnchorSideTop.Control = cmbEncoding
@ -171,7 +248,7 @@ object frmFindDlg: TfrmFindDlg
Left = 146
Height = 29
Top = 2
Width = 555
Width = 544
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 3
BorderSpacing.Right = 3
@ -187,7 +264,7 @@ object frmFindDlg: TfrmFindDlg
Left = 146
Height = 29
Top = 34
Width = 555
Width = 544
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Top = 3
BorderSpacing.Right = 3
@ -244,42 +321,26 @@ object frmFindDlg: TfrmFindDlg
end
end
end
object edtFindPathStart: TDirectoryEdit
AnchorSideLeft.Control = lblFindPathStart
AnchorSideTop.Control = lblFindPathStart
AnchorSideTop.Side = asrBottom
AnchorSideRight.Side = asrBottom
Left = 3
Height = 29
Top = 25
Width = 686
ShowHidden = False
ButtonWidth = 23
NumGlyphs = 1
Anchors = [akTop, akLeft, akRight]
MaxLength = 0
TabOrder = 3
end
object gbFindOptions: TGroupBox
AnchorSideLeft.Control = tsStandard
AnchorSideTop.Control = cmbFindFileMask
AnchorSideTop.Control = cmbExcludeFiles
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = tsStandard
AnchorSideRight.Side = asrBottom
Left = 3
Height = 121
Top = 111
Width = 708
Top = 219
Width = 697
Anchors = [akTop, akLeft, akRight]
AutoSize = True
BorderSpacing.Top = 3
BorderSpacing.Bottom = 3
Caption = 'Options'
ClientHeight = 99
ClientWidth = 704
ClientWidth = 693
ParentFont = False
TabOrder = 1
object cmbFollowSymLinks: TCheckBox
TabOrder = 4
object cbFollowSymLinks: TCheckBox
AnchorSideLeft.Control = cbRegExp
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = cbPartialNameSearch
@ -337,7 +398,7 @@ object frmFindDlg: TfrmFindDlg
Left = 163
Height = 29
Top = 34
Width = 538
Width = 527
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Top = 3
BorderSpacing.Right = 3
@ -389,7 +450,7 @@ object frmFindDlg: TfrmFindDlg
Left = 163
Height = 29
Top = 67
Width = 538
Width = 527
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 3
BorderSpacing.Top = 4
@ -403,8 +464,8 @@ object frmFindDlg: TfrmFindDlg
end
object tsAdvanced: TTabSheet
Caption = 'Advanced'
ClientHeight = 488
ClientWidth = 714
ClientHeight = 512
ClientWidth = 703
ImageIndex = 1
object cbDateFrom: TCheckBox
AnchorSideLeft.Control = tsAdvanced
@ -587,7 +648,7 @@ object frmFindDlg: TfrmFindDlg
Left = 3
Height = 65
Top = 230
Width = 705
Width = 694
Anchors = [akTop, akLeft, akRight]
AutoSize = True
BorderSpacing.Left = 3
@ -597,7 +658,7 @@ object frmFindDlg: TfrmFindDlg
ChildSizing.LeftRightSpacing = 3
ChildSizing.TopBottomSpacing = 6
ClientHeight = 43
ClientWidth = 701
ClientWidth = 690
Constraints.MinWidth = 100
TabOrder = 16
object edtAttrib: TEdit
@ -606,7 +667,7 @@ object frmFindDlg: TfrmFindDlg
Left = 3
Height = 29
Top = 4
Width = 577
Width = 566
HelpType = htKeyword
HelpKeyword = '/findfiles.html#attributes'
Anchors = [akTop, akLeft, akRight]
@ -621,7 +682,7 @@ object frmFindDlg: TfrmFindDlg
AnchorSideTop.Control = edtAttrib
AnchorSideTop.Side = asrCenter
AnchorSideRight.Control = btnAttrsHelp
Left = 583
Left = 572
Height = 31
Top = 3
Width = 53
@ -640,7 +701,7 @@ object frmFindDlg: TfrmFindDlg
AnchorSideRight.Control = gbAttributes
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Side = asrBottom
Left = 639
Left = 628
Height = 33
Top = 2
Width = 59
@ -663,7 +724,7 @@ object frmFindDlg: TfrmFindDlg
Left = 6
Height = 4
Top = 223
Width = 702
Width = 691
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 6
BorderSpacing.Top = 12
@ -781,14 +842,14 @@ object frmFindDlg: TfrmFindDlg
end
object tsLoadSave: TTabSheet
Caption = 'Load/Save'
ClientHeight = 488
ClientWidth = 714
ClientHeight = 512
ClientWidth = 703
OnShow = tsLoadSaveShow
object lblTemplateHeader: TLabel
Left = 3
Height = 22
Top = 3
Width = 708
Width = 697
Align = alTop
BorderSpacing.Left = 3
BorderSpacing.Top = 3
@ -799,9 +860,9 @@ object frmFindDlg: TfrmFindDlg
end
object lbSearchTemplates: TListBox
Left = 3
Height = 396
Height = 420
Top = 25
Width = 708
Width = 697
Align = alClient
BorderSpacing.Left = 3
BorderSpacing.Right = 3
@ -813,8 +874,8 @@ object frmFindDlg: TfrmFindDlg
object lblSearchContents: TPanel
Left = 3
Height = 21
Top = 427
Width = 708
Top = 451
Width = 697
Align = alBottom
Alignment = taLeftJustify
AutoSize = True
@ -828,17 +889,17 @@ object frmFindDlg: TfrmFindDlg
object pnlLoadSaveBottom: TPanel
Left = 3
Height = 31
Top = 454
Width = 708
Top = 478
Width = 697
Align = alBottom
AutoSize = True
BorderSpacing.Around = 3
BevelOuter = bvNone
ClientHeight = 31
ClientWidth = 708
ClientWidth = 697
TabOrder = 2
object pnlLoadSaveBottomButtons: TPanel
Left = 477
Left = 466
Height = 31
Top = 0
Width = 231
@ -895,30 +956,30 @@ object frmFindDlg: TfrmFindDlg
end
object tsResults: TTabSheet
Caption = 'Results'
ClientHeight = 488
ClientWidth = 714
ClientHeight = 512
ClientWidth = 703
object pnlResults: TPanel
AnchorSideTop.Control = pnlFindFile
Left = 0
Height = 488
Height = 512
Top = 0
Width = 714
Width = 703
Align = alClient
BevelOuter = bvNone
ClientHeight = 488
ClientWidth = 714
ClientHeight = 512
ClientWidth = 703
FullRepaint = False
TabOrder = 0
object pnlStatus: TPanel
Left = 0
Height = 50
Top = 0
Width = 714
Width = 703
Align = alTop
AutoSize = True
BevelOuter = bvNone
ClientHeight = 50
ClientWidth = 714
ClientWidth = 703
FullRepaint = False
TabOrder = 0
object lblStatus: TLabel
@ -953,7 +1014,7 @@ object frmFindDlg: TfrmFindDlg
AnchorSideTop.Side = asrCenter
AnchorSideRight.Control = pnlStatus
AnchorSideRight.Side = asrBottom
Left = 667
Left = 656
Height = 22
Top = 28
Width = 44
@ -966,9 +1027,9 @@ object frmFindDlg: TfrmFindDlg
end
object lsFoundedFiles: TListBox
Left = 3
Height = 390
Height = 414
Top = 53
Width = 708
Width = 697
Align = alClient
BorderSpacing.Around = 3
ItemHeight = 0
@ -981,17 +1042,17 @@ object frmFindDlg: TfrmFindDlg
object pnlResultsBottom: TPanel
Left = 3
Height = 39
Top = 446
Width = 708
Top = 470
Width = 697
Align = alBottom
AutoSize = True
BorderSpacing.Around = 3
BevelOuter = bvNone
ClientHeight = 39
ClientWidth = 708
ClientWidth = 697
TabOrder = 2
object pnlResultsBottomButtons: TPanel
Left = 410
Left = 399
Height = 39
Top = 0
Width = 298
@ -1050,8 +1111,8 @@ object frmFindDlg: TfrmFindDlg
end
end
object pnlButtons: TPanel
Left = 728
Height = 482
Left = 717
Height = 506
Top = 40
Width = 112
Align = alRight
@ -1065,7 +1126,7 @@ object frmFindDlg: TfrmFindDlg
ChildSizing.ShrinkHorizontal = crsHomogenousChildResize
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 1
ClientHeight = 482
ClientHeight = 506
ClientWidth = 112
Constraints.MinWidth = 80
TabOrder = 1

View file

@ -1,8 +1,13 @@
TFRMFINDDLG.CAPTION=Find files
TFRMFINDDLG.TSSTANDARD.CAPTION=Standard
TFRMFINDDLG.LBLFINDPATHSTART.CAPTION=&Directory
TFRMFINDDLG.LBLEXCLUDEDIRECTORIES.CAPTION=&Exclude subdirectories
TFRMFINDDLG.CMBEXCLUDEDIRECTORIES.HINT=Enter directories names that should be excluded from search separated with ";"
TFRMFINDDLG.LBLFINDFILEMASK.CAPTION=&File mask
TFRMFINDDLG.CMBFINDFILEMASK.HINT=Enter files names separated with ";"
TFRMFINDDLG.CMBFINDFILEMASK.TEXT=*
TFRMFINDDLG.LBLEXCLUDEFILES.CAPTION=E&xclude files
TFRMFINDDLG.CMBEXCLUDEFILES.HINT=Enter files names that should be excluded from search separated with ";"
TFRMFINDDLG.GBFINDDATA.CAPTION=Find Data
TFRMFINDDLG.LBLENCODING.CAPTION=Encoding:
TFRMFINDDLG.CBCASESENS.CAPTION=Case sens&itive
@ -10,7 +15,7 @@ TFRMFINDDLG.CBNOTCONTAININGTEXT.CAPTION=Find files N&OT containing the text
TFRMFINDDLG.CBFINDTEXT.CAPTION=Find &text in file
TFRMFINDDLG.CBREPLACETEXT.CAPTION=Re&place by
TFRMFINDDLG.GBFINDOPTIONS.CAPTION=Options
TFRMFINDDLG.CMBFOLLOWSYMLINKS.CAPTION=Follow symlinks
TFRMFINDDLG.CBFOLLOWSYMLINKS.CAPTION=Follow symlinks
TFRMFINDDLG.CBREGEXP.CAPTION=&Regular expressions
TFRMFINDDLG.LBLSEARCHDEPTH.CAPTION=Search su&bdirectories:
TFRMFINDDLG.CBPARTIALNAMESEARCH.CAPTION=Search for part of file name

View file

@ -64,7 +64,8 @@ type
cbTimeFrom: TCheckBox;
cbTimeTo: TCheckBox;
cbPartialNameSearch: TCheckBox;
cmbFollowSymLinks: TCheckBox;
cbFollowSymLinks: TCheckBox;
cmbExcludeDirectories: TComboBox;
cmbNotOlderThanUnit: TComboBox;
cmbFileSizeUnit: TComboBox;
cbUsePlugin: TCheckBox;
@ -74,11 +75,14 @@ type
cbRegExp: TCheckBox;
cmbReplaceText: TComboBox;
cmbFindText: TComboBox;
cmbExcludeFiles: TComboBox;
edtFindPathStart: TDirectoryEdit;
edtAttrib: TEdit;
gbAttributes: TGroupBox;
gbFindOptions: TGroupBox;
lblExcludeDirectories: TLabel;
lblCurrent: TLabel;
lblExcludeFiles: TLabel;
lblFound: TLabel;
lblStatus: TLabel;
lblTemplateHeader: TLabel;
@ -269,8 +273,10 @@ begin
begin
// Prepare window for define search template
Caption := rsFindDefineTemplate;
edtFindPathStart.Enabled:= False;
edtFindPathStart.Text:= EmptyStr;
lblFindPathStart.Visible := False;
edtFindPathStart.Visible := False;
lblExcludeDirectories.Visible := False;
cmbExcludeDirectories.Visible := False;
btnSaveTemplate.Visible:= True;
btnStart.Visible:= False;
btnSaveTemplate.Default:= True;
@ -459,7 +465,9 @@ begin
FLastLoadedTemplateName := SearchTemplate.TemplateName;
with SearchTemplate.SearchRecord do
begin
cmbExcludeDirectories.Text:= ExcludeDirectories;
cmbFindFileMask.Text:= FilesMasks;
cmbExcludeFiles.Text:= ExcludeFiles;
if (StartPath <> '') then
edtFindPathStart.Text:= StartPath;
if (SearchDepth + 1 >= 0) and (SearchDepth + 1 < cbSearchDepth.Items.Count) then
@ -468,6 +476,7 @@ begin
cbSearchDepth.ItemIndex:= 0;
cbRegExp.Checked := RegExp;
cbPartialNameSearch.Checked := IsPartialNameSearch;
cbFollowSymLinks.Checked := FollowSymLinks;
// attributes
edtAttrib.Text:= AttributesPattern;
// file date/time
@ -623,11 +632,13 @@ begin
with FindOptions do
begin
StartPath := edtFindPathStart.Text;
ExcludeDirectories := cmbExcludeDirectories.Text;
FilesMasks := cmbFindFileMask.Text;
ExcludeFiles := cmbExcludeFiles.Text;
SearchDepth := cbSearchDepth.ItemIndex - 1;
RegExp := cbRegExp.Checked;
IsPartialNameSearch := cbPartialNameSearch.Checked;
FollowSymLinks := cmbFollowSymLinks.Checked;
FollowSymLinks := cbFollowSymLinks.Checked;
{ File attributes }
AttributesPattern := edtAttrib.Text;

View file

@ -37,7 +37,9 @@ type
TSearchTemplateRec = record
StartPath: String;
ExcludeDirectories: String;
FilesMasks: String;
ExcludeFiles: String;
SearchDepth: Integer; // -1 = unlimited
RegExp: Boolean;
IsPartialNameSearch: Boolean;

View file

@ -51,6 +51,7 @@ type
FLinkTargets: TStringList; // A list of encountered directories (for detecting cycles)
function CheckFile(const Folder : String; const sr : TSearchRecEx) : Boolean;
function CheckDirectory(const CurrentDir, FolderName : String) : Boolean;
function FindInFile(const sFileName:UTF8String;
sData: String; bCase:Boolean): Boolean;
protected
@ -72,7 +73,7 @@ type
implementation
uses
LCLProc, uMasks, SynRegExpr, StrUtils, LConvEncoding,
LCLProc, uMasks, SynRegExpr, StrUtils, LConvEncoding, DCStrUtils,
uLng, DCClassesUtf8, uFindMmap, uGlobs, uShowMsg, DCOSUtils, uOSUtils,
uLog;
@ -98,6 +99,8 @@ begin
// MatchesMaskList work incorrect with non ASCII characters
// since it uses UpCase function
FilesMasks := UTF8UpperCase(FilesMasks);
ExcludeFiles := UTF8UpperCase(ExcludeFiles);
ExcludeDirectories := UTF8UpperCase(ExcludeDirectories);
FindText := ConvertEncoding(FindText, EncodingUTF8, TextEncoding);
ReplaceText := ConvertEncoding(ReplaceText, EncodingUTF8, TextEncoding);
@ -129,8 +132,7 @@ begin
while sTemp <> EmptyStr do
begin
sPath:= Copy2SymbDel(sTemp, ';');
if (Length(sPath) > 1) and (sPath[Length(sPath)] = PathDelim) then
Delete(sPath, Length(sPath), 1);
sPath := ExcludeBackPathDelimiter(sPath);
WalkAdr(sPath);
end;
finally
@ -148,6 +150,41 @@ begin
FItems.Add(FFoundFile);
end;
function TFindThread.CheckDirectory(const CurrentDir, FolderName : String): Boolean;
var
UpperCaseFileName: String;
begin
if (FolderName = '.') or (FolderName = '..') then
Result := False
else
begin
Result := True;
with FSearchTemplate do
begin
if RegExp then
begin
if (ExcludeDirectories <> '') and ExecRegExpr(ExcludeDirectories, FolderName) then
Exit(False);
end
else
begin
UpperCaseFileName := UTF8UpperCase(FolderName);
if MatchesMaskList(UpperCaseFileName, ExcludeDirectories) then
Exit(False);
// Check if FolderName is a path relative to StartPath.
if GetPathType(ExcludeDirectories) = ptRelative then
begin
if ExcludeDirectories = UTF8UpperCase(ExtractDirLevel(
FSearchTemplate.StartPath, CurrentDir + PathDelim + FolderName)) then
Exit(False);
end;
end;
end;
end;
end;
procedure TFindThread.UpDateProgress;
begin
FStatus.Caption:= Format(rsFindScanned, [FFilesScanned]);
@ -274,18 +311,27 @@ begin
end;
function TFindThread.CheckFile(const Folder : String; const sr : TSearchRecEx) : Boolean;
var
UpperCaseFileName: String;
begin
Result := True;
with FSearchTemplate do
begin
// check regular expression
if RegExp and not ExecRegExpr(FilesMasks, sr.Name) then
Exit(False);
//DCDebug('File = ', sr.Name);
if (not RegExp) and (not MatchesMaskList(UTF8UpperCase(sr.Name), FFileChecks.FilesMasks)) then
if RegExp then
begin
if ((FilesMasks <> '') and not ExecRegExpr(FilesMasks, sr.Name)) or
((ExcludeFiles <> '') and ExecRegExpr(ExcludeFiles, sr.Name)) then
Exit(False);
end
else
begin
UpperCaseFileName := UTF8UpperCase(sr.Name);
if not MatchesMaskList(UpperCaseFileName, FilesMasks) or
MatchesMaskList(UpperCaseFileName, ExcludeFiles) then
Exit(False);
end;
if (IsDateFrom or IsDateTo or IsTimeFrom or IsTimeTo or IsNotOlderThan) then
Result := CheckFileTime(FFileChecks, sr.Time);
@ -326,32 +372,32 @@ end;
procedure TFindThread.WalkAdr(const sNewDir:String);
var
sr: TSearchRecEx;
Path,
LinkTarget: UTF8String;
IsLink: Boolean = False;
Path, SubPath: UTF8String;
IsLink: Boolean;
begin
if not mbSetCurrentDir(sNewDir) then Exit;
if Terminated then
Exit;
Inc(FCurrentDepth);
FCurrentDir := sNewDir;
// Search all files to display statistics
Path := sNewDir + PathDelim + '*';
if FindFirstEx(Path, faAnyFile, sr) = 0 then
repeat
if (sr.Name='.') or (sr.Name='..') then Continue;
FCurrentDir:= sNewDir;
Synchronize(@UpDateProgress);
if CheckFile(sNewDir, sr) then
if not FPS_ISDIR(sr.Attr) then
begin
FFoundFile := sNewDir + PathDelim + sr.Name;
Synchronize(@AddFile);
FFilesFound := FFilesFound + 1;
if CheckFile(sNewDir, sr) then
begin
FFoundFile := sNewDir + PathDelim + sr.Name;
Synchronize(@AddFile);
Inc(FFilesFound);
end;
Inc(FFilesScanned);
Synchronize(@UpDateProgress);
end;
inc(FFilesScanned);
until (FindNextEx(sr)<>0) or Terminated;
FindCloseEx(sr);
Synchronize(@UpDateProgress);
@ -359,25 +405,26 @@ begin
{ Search in sub folders }
if (not Terminated) and (FCurrentDepth < FSearchTemplate.SearchDepth) then
begin
Path := sNewDir + PathDelim + '*';
//DCDebug('Search in sub folders = ', Path);
if not Terminated and (FindFirstEx(Path, faDirectory, sr) = 0) then
if FindFirstEx(Path, faDirectory, sr) = 0 then
repeat
IsLink:= FPS_ISLNK(sr.Attr);
if FSearchTemplate.FollowSymLinks and (IsLink = False) then
FLinkTargets.Add(sNewDir + PathDelim + sr.Name) // Add directory where we already searched
else if (FSearchTemplate.FollowSymLinks = False) and IsLink then
Continue
else if FSearchTemplate.FollowSymLinks and IsLink then
if CheckDirectory(sNewDir, sr.Name) then
begin
SubPath := sNewDir + PathDelim + sr.Name;
IsLink := FPS_ISLNK(sr.Attr);
if FSearchTemplate.FollowSymLinks then
begin
LinkTarget:= ReadSymLink(sNewDir + PathDelim + sr.Name);
if FLinkTargets.IndexOf(LinkTarget) >= 0 then
Continue // Link already encountered - links form a cycle.
else
FLinkTargets.Add(LinkTarget); // Add link target where we already searched
end;
if ((sr.Name <> '.') and (sr.Name <> '..')) then
WalkAdr(sNewDir + PathDelim + sr.Name);
if IsLink then
SubPath := mbReadAllLinks(SubPath);
if FLinkTargets.IndexOf(SubPath) >= 0 then
Continue; // Link already encountered - links form a cycle.
// Add directory to already-searched list.
FLinkTargets.Add(SubPath);
end
else if IsLink then
Continue;
WalkAdr(SubPath);
end;
until Terminated or (FindNextEx(sr) <> 0);
FindCloseEx(sr);
end;

View file

@ -84,24 +84,34 @@ function MatchesMask(const FileName, Mask: String; CaseSensitive: Boolean = Fals
var
AMask: TMask;
begin
AMask := TMask.Create(Mask, CaseSensitive);
try
Result := AMask.Matches(FileName);
finally
AMask.Free;
end;
if Mask <> '' then
begin
AMask := TMask.Create(Mask, CaseSensitive);
try
Result := AMask.Matches(FileName);
finally
AMask.Free;
end;
end
else
Result := False;
end;
function MatchesMaskList(const FileName, Mask: String; Separator: Char): Boolean;
var
AMaskList: TMaskList;
begin
AMaskList := TMaskList.Create(Mask, Separator);
try
Result := AMaskList.Matches(FileName);
finally
AMaskList.Free;
end;
if Mask <> '' then
begin
AMaskList := TMaskList.Create(Mask, Separator);
try
Result := AMaskList.Matches(FileName);
finally
AMaskList.Free;
end;
end
else
Result := False;
end;
{ TMask }
@ -317,4 +327,4 @@ begin
end;
end;
end.
end.

View file

@ -101,7 +101,10 @@ begin
with SearchRecord do
begin
if (fpName in AFile.SupportedProperties) then
Result:= MatchesMaskList(AFile.Name, FilesMasks);
begin
Result:= MatchesMaskList(AFile.Name, FilesMasks) and
not MatchesMaskList(AFile.Name, ExcludeFiles);
end;
if Result and (fpModificationTime in AFile.SupportedProperties) then
if (IsDateFrom or IsDateTo or IsTimeFrom or IsTimeTo or IsNotOlderThan) then
@ -255,7 +258,9 @@ begin
begin
SearchTemplate.TemplateName:= AConfig.GetValue(ANode, 'Name', '');
StartPath:= AConfig.GetValue(ANode, 'StartPath', '');
ExcludeDirectories:= AConfig.GetValue(ANode, 'ExcludeDirectories', '');
FilesMasks:= AConfig.GetValue(ANode, 'FilesMasks', '*');
ExcludeFiles:= AConfig.GetValue(ANode, 'ExcludeFiles', '');
SearchDepth:= AConfig.GetValue(ANode, 'SearchDepth', -1);
IsPartialNameSearch:= AConfig.GetValue(ANode, 'IsPartialNameSearch', True);
RegExp:= AConfig.GetValue(ANode, 'RegExp', False);
@ -373,7 +378,9 @@ begin
SubNode := AConfig.AddNode(ANode, 'Template');
AConfig.AddValue(SubNode, 'Name', Templates[I].TemplateName);
AConfig.AddValue(SubNode, 'StartPath', StartPath);
AConfig.AddValue(SubNode, 'ExcludeDirectories', ExcludeDirectories);
AConfig.AddValue(SubNode, 'FilesMasks', FilesMasks);
AConfig.AddValue(SubNode, 'ExcludeFiles', ExcludeFiles);
AConfig.AddValue(SubNode, 'SearchDepth', SearchDepth);
AConfig.AddValue(SubNode, 'IsPartialNameSearch', IsPartialNameSearch);
AConfig.AddValue(SubNode, 'RegExp', RegExp);
@ -419,4 +426,4 @@ begin
end;
end.