Консультация № 161432
26.02.2009, 01:27
0.00 руб.
0 10 0
Имеется процедура выполняющая поиск файла в каталоге и его подкаталогах:

Код:

procedure FindFiles(StartFolder, Mask: string; List: TStrings;
ScanSubFolders: Boolean = True);
var
SearchRec: TSearchRec;
FindResult: Integer;
begin
List.BeginUpdate;
try
StartFolder := IncludeTrailingBackslash(StartFolder);
FindResult := FindFirst(StartFolder + '*.*', faAnyFile, SearchRec);
try
while FindResult = 0 do
with SearchRec do
begin
if (Attr and faDirectory) <> 0 then
begin
if ScanSubFolders and (Name <> '.') and (Name <> '..') then
FindFiles(StartFolder + Name, Mask, List, ScanSubFolders);
end
else
begin
if MatchesMask(Name, Mask) then
List.Add(StartFolder + Name);
end;
FindResult := FindNext(SearchRec);
end;
finally
FindClose(SearchRec);
end;
finally
List.EndUpdate;
end;
end;


Бью голову уже который день (перед этим с подобными ситуациями дела не имел): как можно осуществить такой же поиск (с подкаталогами) но не файла, а папки, причем хотелось бы, чтобы процедура выполняла поиск по первым буквам названия папки (допусти нужно найти все папки, имена которых начинаются с "test". имеем папки test1,test2,testA,testB и т.д.)

Благодарю за внимание и помощь

Обсуждение

давно
Мастер-Эксперт
425
4118
26.02.2009, 05:32
общий
Сейчас у Вас условие отбора - что угодно. Вам нужно только конкретизировать отбор:
Код:
if (Attr and faDirectory) = faDirectory then

Т.е. Вы на полученый аттрибут файла накладываете маску - "faDirectory". Помните фильм "Шерлок Холмс и доктор Ватсон"? Помните как в начале фильма идут титры? Вам нужно делать то же самое. И если после наложения маски появился искомый результат, значит это оно и есть.
Маска имени задаётся в функции FindFirst:
Код:
FindFirst(StartFolder + 'test*.*', faAnyFile, SearchRec)

Звёздочка означает, что вместо неё могут стоять любые символы в любом количестве.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
26.02.2009, 06:46
общий
sir Henry, дело в том, что faDirectory = $00000010 т.е хоть (Attr and faDirectory) = faDirectory, хоть (Attr and faDirectory) <> 0 дадут одинаковый результат. Поэтому ничего не изменится. Не проще ли сразу задать атрибут поиска как
Код:

FindResult := FindFirst(StartFolder + '*.*', faDirectory , SearchRec)

давно
Мастер-Эксперт
425
4118
26.02.2009, 07:50
общий
Micren

А Вы попробуйте сами применить свой совет, а потом скажите, что у Вас получилось.
Или, если у Вас нет проблем с английским, загляните в хелп и посмотрите, что там пишут по поводу аттрибутов.
Я Вам даже облегчу задачу. Вот консольная программка, откомпилируйте и запустите её:
Код:
Uses SysUtils ;
var
sr: TSearchRec;
begin
if FindFirst('*.*', faDirectory, sr) = 0 then
repeat
if (sr.Attr and faDirectory) = faDirectory then
WriteLn(sr.Name, ' ', sr.attr)
else
WriteLn(sr.attr);
until FindNext(sr) <> 0;
FindClose(sr);
end.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
26.02.2009, 11:31
общий
sir Henry, Micren, спасибо большое обоим, НО есть один ньюанс....

Пример sir Henry с консольной программкой работает на 100%, но производит поиск только в текущей директории, а хотелось бы и в поддиректориях. Если сможете и с этим помочь - было бы вообще хорошо
давно
Мастер-Эксперт
425
4118
26.02.2009, 12:28
общий
Segey
То что я писал Micren'у это было не для Вас, а только ему. Я Вам написал условие для выбора каталогов.
Вы вообще представляете, как работает рекурсивный поиск или нужно рассказывать алгоритм?
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
26.02.2009, 15:01
общий
sir Henry, рекурсивный? Т.е. это вызов процедурой себя же... вроде так.
Я Вам написал условие для выбора каталогов.
к сожалению не получается осуществить поиск таким образом, можно ли пример готовой процедуры?

P.S. я новичок, сильно не ругайте ;)
давно
Мастер-Эксперт
425
4118
26.02.2009, 16:44
общий
Т.е. это вызов процедурой себя же...

Применительно к поиску файлов термин "рекурсивный" имеет несколько другое значение. Если представить поиск в виде паровоза, то наш паровоз будет заезжать в каждый всиреченный им каталог, сколько бы их ни было вложено друг в друга. Это похоже на рекурсию в программировании, но не совсем...
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
26.02.2009, 18:35
общий
sir Henry,
Насчет того, что писать if (Attr and faDirectory) = faDirectory then, или if (Attr and faDirectory) <> 0 then так это тавтология чистой воды. Если Вы хотя бы немного подумаете, то поймете, что в этом Вашем совете смысла нет. Это все равно, что спорить о том как правильнее писать a=b, или not (a<>b).

А насчет остального Вы правы.
давно
Мастер-Эксперт
425
4118
26.02.2009, 18:47
общий
Micren
Я, конечно, понимаю, что Вам охота повыпендриваться за мой счёт, но всё-таки постарайтесь от этого воздержаться, если у Вас нет каких-то существенных добавлений на тему вопроса.
Больше я Вас предупреждать не буду.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Мастер-Эксперт
425
4118
26.02.2009, 19:21
общий
Segey
А слона то я и не заметил. У Вас там секция else лишняя. Вот смотрите:
Код:
procedure FindFiles(StartFolder, Mask: string; List: TStringList;
ScanSubFolders: Boolean = True);
var
SearchRec: TSearchRec;
FindResult: Integer;
begin
List.BeginUpdate;
try
StartFolder := IncludeTrailingBackslash(StartFolder);
FindResult := FindFirst(StartFolder + '*.*', faAnyFile, SearchRec);
try
while FindResult = 0 do
with SearchRec do
begin
if (Attr and faDirectory) = faDirectory then
if ScanSubFolders and (Name <> '.') and (Name <> '..') then
begin
FindFiles(StartFolder + Name, Mask, List, ScanSubFolders);
List.Add(StartFolder + Name);
end;
FindResult := FindNext(SearchRec);
end;
finally
FindClose(SearchRec);
end;
finally
List.EndUpdate;
end;
end;
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Форма ответа