Консультация онлайн # 161432

Раздел: Pascal / Delphi / Lazarus
Автор вопроса: Segey
Дата: 26.02.2009, 01:27 Консультация неактивна
Поступило ответов: 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 и т.д.)

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

Ответов еще не поступило.

Мини-форум консультации # 161432

Вадим Исаев ака sir Henry

Мастер-Эксперт

ID: 425

177858

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

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

Звёздочка означает, что вместо неё могут стоять любые символы в любом количестве.
=====
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Micren

177859

= общий =    26.02.2009, 06:46
sir Henry, дело в том, что faDirectory = $00000010 т.е хоть (Attr and faDirectory) = faDirectory, хоть (Attr and faDirectory) <> 0 дадут одинаковый результат. Поэтому ничего не изменится. Не проще ли сразу задать атрибут поиска как
Код
FindResult := FindFirst(StartFolder + '*.*', faDirectory , SearchRec)

Вадим Исаев ака sir Henry

Мастер-Эксперт

ID: 425

177861

= общий =    26.02.2009, 07:50
Micren
smile
А Вы попробуйте сами применить свой совет, а потом скажите, что у Вас получилось.
Или, если у Вас нет проблем с английским, загляните в хелп и посмотрите, что там пишут по поводу аттрибутов.
Я Вам даже облегчу задачу. Вот консольная программка, откомпилируйте и запустите её:
Код
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.
=====
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
неизвестный

177889

= общий =    26.02.2009, 11:31
sir Henry, Micren, спасибо большое обоим, НО есть один ньюанс....

Пример sir Henry с консольной программкой работает на 100%, но производит поиск только в текущей директории, а хотелось бы и в поддиректориях. Если сможете и с этим помочь - было бы вообще хорошо smile
Вадим Исаев ака sir Henry

Мастер-Эксперт

ID: 425

177894

= общий =    26.02.2009, 12:28
Segey
То что я писал Micren'у это было не для Вас, а только ему. Я Вам написал условие для выбора каталогов.
Вы вообще представляете, как работает рекурсивный поиск или нужно рассказывать алгоритм?
=====
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
неизвестный

177912

= общий =    26.02.2009, 15:01
sir Henry, рекурсивный? Т.е. это вызов процедурой себя же... вроде так.

Я Вам написал условие для выбора каталогов.

к сожалению не получается осуществить поиск таким образом, можно ли пример готовой процедуры?

P.S. я новичок, сильно не ругайте ;)
Вадим Исаев ака sir Henry

Мастер-Эксперт

ID: 425

177930

= общий =    26.02.2009, 16:44

Т.е. это вызов процедурой себя же...


Применительно к поиску файлов термин "рекурсивный" имеет несколько другое значение. Если представить поиск в виде паровоза, то наш паровоз будет заезжать в каждый всиреченный им каталог, сколько бы их ни было вложено друг в друга. Это похоже на рекурсию в программировании, но не совсем...
=====
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Micren

177949

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

А насчет остального Вы правы.
Вадим Исаев ака sir Henry

Мастер-Эксперт

ID: 425

177952

= общий =    26.02.2009, 18:47
Micren
Я, конечно, понимаю, что Вам охота повыпендриваться за мой счёт, но всё-таки постарайтесь от этого воздержаться, если у Вас нет каких-то существенных добавлений на тему вопроса.
Больше я Вас предупреждать не буду.
=====
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Вадим Исаев ака sir Henry

Мастер-Эксперт

ID: 425

177958

= общий =    26.02.2009, 19:21
Segey
А слона то я и не заметил. smile У Вас там секция 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;
=====
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Возможность оставлять сообщения в мини-форумах консультаций доступна только после входа в систему.
Воспользуйтесь кнопкой входа вверху страницы, если Вы зарегистрированы или пройдите простую процедуру регистрации на Портале.