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

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

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

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

Сообщение Сквозняк » 06.12.2017 03:54:57

Код: Выделить всё
FindFirst ('*/*/*uz',faAnyFile and faDirectory,Info)

Что за подлость такая? FindFirst находит в дереве каталогов искомый файл но не кладёт в Info путь к нему, а не зная пути, файл не открыть. Есть ли в fpc решение этой проблемы?
Сквозняк
энтузиаст
 
Сообщения: 1109
Зарегистрирован: 29.06.2006 22:08:32

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

Сообщение wadman » 06.12.2017 10:04:42

ОС какая?
wadman
постоялец
 
Сообщения: 122
Зарегистрирован: 18.10.2016 15:54:28

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

Сообщение Сквозняк » 06.12.2017 14:29:11

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

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

Сообщение runewalsh » 06.12.2017 14:55:25

В Windows не поддерживаются подстановочные символы вне последнего компонента пути (поэтому и вопроса такого не стоит, хех, можно просто конкатенировать с путём из запроса). Неужели Linux поддерживает? Искать среди */*/* потенциально очень долго.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

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

Сообщение Сквозняк » 06.12.2017 15:45:49

Да, линукс среди */*/* ищет, может это и долго, но зато для человека - быстро. В линуксовом sysutils куча кода для поиска, есть данные с указателем на путь, только наружу из модуля ничего не торчит.
Сквозняк
энтузиаст
 
Сообщения: 1109
Зарегистрирован: 29.06.2006 22:08:32

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

Сообщение wadman » 06.12.2017 17:29:55

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

Не быстрее, чем рекурсия по папкам. Но да, придется программировать и это печально. За то написать нужно один раз.
wadman
постоялец
 
Сообщения: 122
Зарегистрирован: 18.10.2016 15:54:28

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

Сообщение Сквозняк » 06.12.2017 18:27:41

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

По сути придётся написать аналог кода содержащегося в линуксовом sysutils и таскать его с собой. Единственное улучшение - вместо strirg будет использоваться ansystring, и длинные пути в них поместятся.
Сквозняк
энтузиаст
 
Сообщения: 1109
Зарегистрирован: 29.06.2006 22:08:32

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

Сообщение olegy123 » 06.12.2017 19:07:18

olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

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

Сообщение Сквозняк » 06.12.2017 20:41:11

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

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

Сообщение wadman » 07.12.2017 09:50:46

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

Будто это нечто тяжелое. :) Это может быть вовсе не фишкой линуксового sysutils (тогда можно просто содрать код и "таскать"), а часть самого линукса.
wadman
постоялец
 
Сообщения: 122
Зарегистрирован: 18.10.2016 15:54:28

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

Сообщение Сквозняк » 07.12.2017 15:48:57

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:
Сквозняк
энтузиаст
 
Сообщения: 1109
Зарегистрирован: 29.06.2006 22:08:32

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

Сообщение sign » 08.12.2017 07:10:05

Потому что:

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
sign
энтузиаст
 
Сообщения: 1131
Зарегистрирован: 30.08.2009 09:20:53

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

Сообщение wofs » 08.12.2017 09:50:07

Сквозняк писал(а):Единственное улучшение - вместо 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
Аватара пользователя
wofs
постоялец
 
Сообщения: 379
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань

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

Сообщение runewalsh » 08.12.2017 11:36:43

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

Хотя в общем случае вариант с mask and flag = flag чуть «лучше» в том смысле, что ожидаемо работает, если вдруг в flag будет более одной двоичной единицы (проверит совпадения всех, а не хотя бы одной). Но это редко нужно.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0

Рейтинг@Mail.ru