FindFirst - как найти путь

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Ответить
Сквозняк
энтузиаст
Сообщения: 1159
Зарегистрирован: 29.06.2006 22:08:32

FindFirst - как найти путь

Сообщение Сквозняк »

Код: Выделить всё

FindFirst ('*/*/*uz',faAnyFile and faDirectory,Info)

Что за подлость такая? FindFirst находит в дереве каталогов искомый файл но не кладёт в Info путь к нему, а не зная пути, файл не открыть. Есть ли в fpc решение этой проблемы?
wadman
постоялец
Сообщения: 122
Зарегистрирован: 18.10.2016 14:54:28
Контактная информация:

Сообщение wadman »

ОС какая?
Сквозняк
энтузиаст
Сообщения: 1159
Зарегистрирован: 29.06.2006 22:08:32

Сообщение Сквозняк »

Линукс, но желательно и для винды тоже.
Аватара пользователя
runewalsh
энтузиаст
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Сообщение runewalsh »

В Windows не поддерживаются подстановочные символы вне последнего компонента пути (поэтому и вопроса такого не стоит, хех, можно просто конкатенировать с путём из запроса). Неужели Linux поддерживает? Искать среди */*/* потенциально очень долго.
Сквозняк
энтузиаст
Сообщения: 1159
Зарегистрирован: 29.06.2006 22:08:32

Сообщение Сквозняк »

Да, линукс среди */*/* ищет, может это и долго, но зато для человека - быстро. В линуксовом sysutils куча кода для поиска, есть данные с указателем на путь, только наружу из модуля ничего не торчит.
wadman
постоялец
Сообщения: 122
Зарегистрирован: 18.10.2016 14:54:28
Контактная информация:

Сообщение wadman »

Сквозняк писал(а):но зато для человека - быстро.

Не быстрее, чем рекурсия по папкам. Но да, придется программировать и это печально. За то написать нужно один раз.
Сквозняк
энтузиаст
Сообщения: 1159
Зарегистрирован: 29.06.2006 22:08:32

Сообщение Сквозняк »

wadman писал(а):Но да, придется программировать и это печально. За то написать нужно один раз.

По сути придётся написать аналог кода содержащегося в линуксовом sysutils и таскать его с собой. Единственное улучшение - вместо strirg будет использоваться ansystring, и длинные пути в них поместятся.
olegy123
долгожитель
Сообщения: 1643
Зарегистрирован: 25.02.2016 11:10:20

Сообщение olegy123 »

Сквозняк
энтузиаст
Сообщения: 1159
Зарегистрирован: 29.06.2006 22:08:32

Сообщение Сквозняк »

Не хотелось бы без нужды привязываться к таким зависимостям и лишний раз качать данные через баш и посикс утилиты.
wadman
постоялец
Сообщения: 122
Зарегистрирован: 18.10.2016 14:54:28
Контактная информация:

Сообщение wadman »

Сквозняк писал(а):и таскать его с собой.

Будто это нечто тяжелое. :) Это может быть вовсе не фишкой линуксового sysutils (тогда можно просто содрать код и "таскать"), а часть самого линукса.
Сквозняк
энтузиаст
Сообщения: 1159
Зарегистрирован: 29.06.2006 22:08:32

Сообщение Сквозняк »

ldd показывает что программа с sysutils.findfirst не имеет в линуксе библиотек-зависимостей, не является объектным файлом, то есть зависит только от ядра и среды в целом. Форкнуть sysutils и прицепить к коду, тоже не вариант - у того вообще куча зависимостей, которые не так просто собираются. Проще всё-таки написать код "послойно" складывающий названия каталогов в массивы удлиняемой длины. Но тут возникает другая проблема:

Код: Выделить всё

//Поиск каталогов
uses
sysutils;

var
FII: TSearchRec;

begin
sysutils.FindFirst('*',faDirectory,FII);
writeln(FII.NAME);
while sysutils.FindNext(FII)=0 do writeln('____ ',FII.NAME);
end.

Ищутся на только каталоги, а вообще весь хлам что в них есть. Можно ли натравить поисковик конкретно только на каталоги?

Добавлено спустя 7 часов 9 минут 52 секунды:
Поискал примеры и исправил тестовую программу:

Код: Выделить всё

//Поиск каталогов
uses
sysutils;

var
FII: TSearchRec;

begin
sysutils.FindFirst('*',faAnyFile and faDirectory,FII);
if FII.ATTR=faDirectory then writeln('____ ',FII.NAME);
while sysutils.FindNext(FII)=0 do
 if (FII.attr and faDirectory)=faDirectory
   then if FII.NAME<>'.' then if FII.NAME<>'..'
     then writeln('FII.attr=',FII.attr,' faDirectory=',faDirectory,'____ ',FII.NAME);
sysutils.FindClose(FII);
end.

Пример работы:

Код: Выделить всё

$ ./z
FII.attr=49 faDirectory=16____ 0000
FII.attr=49 faDirectory=16____ 99
FII.attr=48 faDirectory=16____ root
FII.attr=48 faDirectory=16____ 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwweeeeeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrfffffffffffffffffffffffffffffffffffffffffffffffffffff
FII.attr=48 faDirectory=16____ 4444
В принципе находится всё правильно, но (FII.attr and faDirectory)=faDirectory - это какой-то логический сифилис :x При FII.attr=32 и FII.attr=33 сравнение ложно, а при FII.attr=48 и FII.attr=49 - истинно. Это как?

Ясно, у 48, 49 и 16 есть одинаковая единичка в двоичной грамоте и потому эти числа одинаковые :mrgreen:
sign
энтузиаст
Сообщения: 1131
Зарегистрирован: 30.08.2009 09:20:53

Сообщение sign »

Потому что:

010000 - faDirectory
100000 - 32
100001 - 33
110000 - 48
110001 - 49

Отсюда:

(010000 and 100000) = 0
(010000 and 100001) = 0
(010000 and 110000) = 1
(010000 and 110001) = 1
Аватара пользователя
wofs
постоялец
Сообщения: 379
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань
Контактная информация:

Сообщение wofs »

Сквозняк писал(а):Единственное улучшение - вместо strirg будет использоваться ansystring, и длинные пути в них поместятся.

string по умолчанию и так ansistring в fpc.
Ибо

String

The type String may refer to ShortString or AnsiString, depending from the {$H} switch. If the switch is off ({$H-}) then any string declaration will define a ShortString. It size will be 255 chars, if not otherwise specified. If it is on ({$H+}) string without length specifier will define an AnsiString, otherwise a ShortString with specified length. In mode delphiunicode' String is UnicodeString.

http://wiki.freepascal.org/Character_and_string_types
Аватара пользователя
runewalsh
энтузиаст
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Сообщение runewalsh »

Обычно идиомой FII.attr and faDirectory <> 0 делают (МОЖНО ДАЖЕ СКОБКИ НЕ СТАВИТЬ, ОФИГЕТЬ).

Хотя в общем случае вариант с mask and flag = flag чуть «лучше» в том смысле, что ожидаемо работает, если вдруг в flag будет более одной двоичной единицы (проверит совпадения всех, а не хотя бы одной). Но это редко нужно.
Ответить