Помощь - Поиск - Пользователи - Календарь
Полная версия: Поиск файла, название известно, поддиректория - нет.
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Делфи
TarasBer
Res := FindFirst('Models\*\ЛМ-68.md', faAnyFile, F);
Не находит.
Если сказать тупо:
Res := FindFirst('Models\ЛМ, ЛВС\ЛМ-68.md', faAnyFile, F);
То да, он честно находит ЛМ-68.md
Но название папки-то заранее не известно, вот в чём суть.
volvo
FindFirst - вообще очень глючна, причем это не проблема Дельфи, это проблема Windows: Embarcadero QC: FindFirst/FindNext wildcard error

Что касается Дельфи, то там явно сказано, что
Цитата
The FileMask may contain a path, as well as a file name. The file name may contain wild cards:

? : Match any one character
* : Match 0, 1 or more characters
, то есть, шаблоны допустимы только в имени файла, но не в пути к нему.
TarasBer
Да я вообще понимаю, что эта функция - часть ОС.
Но мне что тогда делать-то?

И ещё, немного оффтоп - как известные файловые менеджеры определяют, является ли то, что скрывается под именем, каталогом, или просто файлом? Финдфирст тупо смотрит на наличие точки в имени, то есть он не катит.
volvo
Цитата
Но мне что тогда делать-то?
Я бы, наверное, написал функцию, проверяющую, подходит ли имя файла под заданный шаблон. И ищи файлы рекурсивно во всех папках, начиная с той, что ДО звездочки. Нашел - проверил полное имя. Подходит под шаблон - хорошо, не подходит - ищи дальше...



TarasBer
Но для этого надо написать поиск папок, а этого я тоже не умею, так как параметр faDir выдаст мне просто названия файлов без точки. Если в назвинии папки окажется точка, то как я её вычислю?
volvo
Цитата
Но для этого надо написать поиск папок, а этого я тоже не умею так как параметр faDir выдаст мне просто названия файлов без точки
А не надо искать с faDir, ищи с faAnyFile и потом проверяй поле SearchRec.Attr ...

Кстати, ничего писать самому уже не надо (в смысле, соответствие маске), все есть в Дельфи...
uses { ... ,} Masks;

procedure FindFiles(const Path, Mask: String; FileList: TStrings);
var
SRec: TSearchRec;
Dir: string;
begin
Dir := IncludeTrailingPathDelimiter(Path);
if FindFirst(Dir + '*.*', faAnyFile, SRec) <> 0 then Exit;
try
repeat
if (SRec.Name = '.') or (SRec.Name = '..') then Continue;
if (SRec.Attr and faDirectory) = faDirectory then // Вот проверка, папка или нет
FindFiles(Dir + SRec.Name, Mask, FileList)
else
begin
if MatchesMask(Dir + SRec.Name, Mask) then
begin
FileList.Add(Dir + SRec.Name);
end;
end;
until FindNext(SRec) <> 0;
finally
FindClose(SRec);
end;
end;

// Вызывать так:
FindFiles('F:\Programs', 'F:\Programs\*\bcd.txt', Memo1.Lines);
TarasBer
Сделал по аналогии, заработало, спасибо.
Unconnected
У меня, помню, постоянно на строке FindClose(SRec); ошибка выскакивала, если в консоли вышеприведенное использовать.
volvo
Не знаю, только что гонял в консоли, работает, зараза... А чего за ошибку-то выдавало, не проверял?
Unconnected
В такой процедуре в консоли:

Procedure ScanDir(Dir:string);
var
searchrec:tsearchrec;
begin
if Dir<>'' then if Dir[length(Dir)]<>'\' then Dir:=Dir+'\';
if FindFirst(Dir+'*.*', faAnyFile, SearchRec)=0 then
repeat
if (SearchRec.name='.') or (SearchRec.name='..') then continue;
if (SearchRec.Attr and faDirectory)<>0 then
ScanDir(Dir+SearchRec.name)
else
if extractfileext(Dir+SearchRec.name)='.qhf' then zip1.AddFiles(Dir+SearchRec.name);
if searchrec.name='owner.mdb' then zip1.AddFiles(Dir+SearchRec.name);
until FindNext(SearchRec)<>0;
FindClose(SearchRec); //<------
end;


На выделенной строке выдаёт Incompatible types: 'Cardinal' and 'TSearchRec'. Я эту строку просто "закомментировывал", и ничего страшного не происходило:)
volvo
Цитата
На выделенной строке выдаёт Incompatible types: 'Cardinal' and 'TSearchRec'
А в Uses поменять местами SysUtils и Windows (чтоб SysUtils был подключен ПОСЛЕ Windows) не догадался? Есть же WinAPI-функция FindClose, которая получает хендл файла. А в Паскаль/Дельфи есть не очень приятная особенность: описание функции в модуле подключенном ПОЗЖЕ перекрывает описание, имеющееся в модуле, подключенном РАНЬШЕ. Так что либо как я написал выше (менять модули местами при подключении), либо
SysUtils.FindClose(SearchRec);
, но вызывать ее надо. Иначе получишь утечку ресурсов...
Unconnected
А в Uses поменять местами SysUtils и Windows (чтоб SysUtils был подключен ПОСЛЕ Windows) не догадался? 


Такую апи-функцию знаю, но всё равно ни за что бы не догадался:)
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.