Findfirst, findnext поиск файлов по шаблону


Содержание

FindFirst/FindNext обнаруживает неправильные файлы

Я кодирую в Borland С++ Builder 6. В нескольких моих приложениях я использую следующую функцию для поиска файлов в нашей сети:

Это утомительная версия функции, но вы можете видеть, что я пытаюсь выполнить. Я попытался найти любой файл на N: с маской 748000*.* .

Однако функция возвращает файлы, которые не соответствуют маске. После некоторого рытья я обнаружил, что это связано с 8.3 короткими именами файлов. По какой-то причине короткие имена файлов полностью ошибочны. Например, 748123_20201110.pdf должен выглядеть примерно как 748123

1.pdf , вместо этого он показывает 748AE4

1.PDF . Я знаю обход (проверяя значение «Имя» в найденном файле, которое дало бы мне полное имя, а затем проверило бы полное имя). Однако это безумие.

У меня есть несколько вопросов здесь:

Почему короткие имена будут отформатированы неправильно?

Можно ли найти FindFirst() / FindNext() для поиска только длинных имен файлов? Если нет, есть ли у кого-нибудь альтернативная функция, которая может быть использована?

Существует команда DOS для полного отключения коротких имен. Существуют ли какие-либо опасности при этом? Кроме того, если я отключу эту опцию на нашем сетевом диске, этого будет достаточно? Все файловые операции выполняются с ПК конечного пользователя (мне нужно отключить короткие имена на отдельных ПК?

Эти функции осуществляют и завершают поиск для указанных имен файлов: These functions search for and close searches for specified file names:

Примечания Remarks

Функция _findfirst предоставляет сведения о первом экземпляре имени файла, соответствующем файлу, указанному в аргументе filespec . The _findfirst function provides information about the first instance of a file name that matches the file specified in the filespec argument. В filespec можно использовать любые комбинации подстановочных знаков, которые поддерживаются операционной системой. You can use in filespec any combination of wildcard characters that is supported by the host operating system.

Функции возвращают сведения о файле в структуре _finddata_t , которая определена в IO.h. The functions return file information in a _finddata_t structure, which is defined in IO.h. Различные функции в данном семействе используют множество вариантов структуры _finddata_t . Various functions in the family use many variations on the _finddata_t structure. Базовая структура _finddata_t содержит следующие элементы: The basic _finddata_t structure includes the following elements:

unsigned attrib
Атрибут файла. File attribute.

time_t time_create
Время создания файла (–1L для файловых систем FAT). Time of file creation (-1L for FAT file systems). Это время хранится в формате UTC. This time is stored in UTC format. Для преобразования в местное время используйте функцию localtime_s. To convert to the local time, use localtime_s.

time_t time_access
Время последнего доступа к файлу (–1L для файловых систем FAT). Time of the last file access (-1L for FAT file systems). Это время хранится в формате UTC. This time is stored in UTC format. Для преобразования в местное время используйте функцию localtime_s . To convert to the local time, use localtime_s .

time_t time_write
Время последней записи в файл. Time of the last write to file. Это время хранится в формате UTC. This time is stored in UTC format. Для преобразования в местное время используйте функцию localtime_s . To convert to the local time, use localtime_s .

_fsize_t size
Длина файла в байтах. Length of the file in bytes.

char name [ _MAX_PATH ] Имя соответствующего файла или каталога без пути с конечным нуль-символом. char name [ _MAX_PATH ] Null-terminated name of matched file or directory, without the path.

В файловых системах, которые не поддерживают время создания и последнего обращения к файлу (например, в системе FAT), поля time_create и time_access всегда содержат значение –1L. In file systems that do not support the creation and last access times of a file, such as the FAT system, the time_create and time_access fields are always -1L.

_MAX_PATH определен в Stdlib.h как 260 байт. _MAX_PATH is defined in Stdlib.h as 260 bytes.

Задание целевых атрибутов (например _A_RDONLY ) для ограничения операции поиска невозможно. You cannot specify target attributes (such as _A_RDONLY ) to limit the find operation. Эти атрибуты возвращаются в поле attrib структуры _finddata_t и могут иметь следующие значения (определенные в IO.h). These attributes are returned in the attrib field of the _finddata_t structure and can have the following values (defined in IO.h). Пользователи не должны считать эти значения единственно возможными для поля attrib . Users should not rely on these being the only values possible for the attrib field.

_A_ARCH
Архив. Archive. Устанавливается при изменении файла и очищается командой BACKUP . Set whenever the file is changed and cleared by the BACKUP command. Значение: 0x20. Value: 0x20.

_A_HIDDEN
Скрытый файл. Hidden file. Обычно не виден команде DIR, если не используется параметр /AH . Not generally seen with the DIR command, unless you use the /AH option. Возвращает сведения об обычных файлах и файлах, имеющих этот атрибут. Returns information about normal files and files that have this attribute. Значение: 0x02. Value: 0x02.

_A_NORMAL
Нормальный. Normal. У файла не установлены никакие другие атрибуты, чтение и запись возможны без ограничений. File has no other attributes set and can be read or written to without restriction. Значение: 0x00. Value: 0x00.

_A_RDONLY
Только для чтения. Read-only. Файл невозможно открыть для записи; также невозможно создать файл с этим именем. File cannot be opened for writing and a file that has the same name cannot be created. Значение: 0x01. Value: 0x01.

_A_SUBDIR
Подкаталог. Subdirectory. Значение: 0x10. Value: 0x10.

_A_SYSTEM
Системный файл. System file. Обычно не виден команде DIR , если не используется параметр /A или /A:S . Not ordinarily seen with the DIR command, unless the /A or /A:S option is used. Значение: 0x04. Value: 0x04.

Функция _findnext находит следующее имя, если таковое имеется, которое соответствует аргументу filespec , указанному в предыдущем вызове функции _findfirst . _findnext finds the next name, if any, that matches the filespec argument specified in an earlier call to _findfirst . Аргумент fileinfo должен указывать на структуру, инициализированную предыдущим вызовом функции _findfirst . The fileinfo argument should point to a structure initialized by the previous call to _findfirst . Если обнаружено соответствие, содержимое структуры fileinfo изменяется, как описано выше. If a match is found, the fileinfo structure contents are changed as described earlier. В противном случае оно остается неизменным. Otherwise, it is left unchanged. Функция _findclose закрывает указанный дескриптор поиска и освобождает все связанные ресурсы для функций _findfirst и _findnext . _findclose closes the specified search handle and releases all associated resources for both _findfirst and _findnext . Дескриптор, возвращенный ранее функцией _findfirst или _findnext , необходимо сначала передать в функцию _findclose , чтобы можно было выполнять операции изменения (например, удаление) в каталогах, которые образуют переданные им пути. The handle returned by either _findfirst or _findnext must first be passed to _findclose , before modification operations, such as deleting, can be performed on the directories that form the paths passed to them.

Функции _find допускают вложение. You can nest the _find functions. Например, если вызов функции _findfirst или _findnext нашел файл, являющийся подкаталогом, новый поиск можно начать другим вызовом функции _findfirst или _findnext . For example, if a call to _findfirst or _findnext finds the file that is a subdirectory, a new search can be initiated with another call to _findfirst or _findnext .

_wfindfirst и _wfindnext — это версии функций _findfirst и _findnext для расширенных символов. _wfindfirst and _wfindnext are wide-character versions of _findfirst and _findnext . Аргумент структуры версий для расширенных символов имеет тип данных _wfinddata_t , который определен в файлах IO.h и Wchar.h. The structure argument of the wide-character versions has the _wfinddata_t data type, which is defined in IO.h and in Wchar.h. Поля этого типа данных совпадают с полями типа данных _finddata_t , за исключением того, что в _wfinddata_t поле имени имеет тип wchar_t , а не тип char . The fields of this data type are the same as those of the _finddata_t data type, except that in _wfinddata_t the name field is of type wchar_t instead of type char . В остальном поведение функций _wfindfirst и _wfindnext не отличается от поведения функций _findfirst и _findnext . Otherwise _wfindfirst and _wfindnext behave identically to _findfirst and _findnext .

Функции _findfirst и _findnext используют 64-разрядный тип времени. _findfirst and _findnext use the 64-bit time type. Если необходимо использовать прежний 32-разрядный тип времени, можно определить _USE_32BIT_TIME_T . If you must use the old 32-bit time type, you can define _USE_32BIT_TIME_T . Версии этих функций, в именах которых имеется суффикс 32 , используют 32-разрядный тип времени; версии с суффиксом 64 используют 64-разрядный тип времени. The versions of these functions that have the 32 suffix in their names use the 32-bit time type, and those with the 64 suffix use the 64-bit time type.

Функции _findfirst32i64 , _findnext32i64 , _wfindfirst32i64 и _wfindnext32i64 также ведут себя идентично версиям этих функций с 32-разрядным типом времени, за исключением того, что они используют и возвращают 64-разрядные значения длины файлов. Functions _findfirst32i64 , _findnext32i64 , _wfindfirst32i64 , and _wfindnext32i64 also behave identically to the 32-bit time type versions of these functions except they use and return 64-bit file lengths. Функции _findfirst64i32 , _findnext64i32 , _wfindfirst64i32 и _wfindnext64i32 используют 64-разрядный тип времени, но 32-разрядные значения длины файлов. Functions _findfirst64i32 , _findnext64i32 , _wfindfirst64i32 , and _wfindnext64i32 use the 64-bit time type but use 32-bit file lengths. Эти функции используют соответствующие варианты типа _finddata_t , в которых поля имеют разные типы для времени и размера файла. These functions use appropriate variations of the _finddata_t type in which the fields have different types for the time and the file size.

_finddata_t фактически представляет собой макрос, который преобразуется в _finddata64i32_t (или _finddata32_t , если определена константа _USE_32BIT_TIME_T ). _finddata_t is actually a macro that evaluates to _finddata64i32_t (or _finddata32_t if _USE_32BIT_TIME_T is defined). В следующей таблице приведены сводные сведения об этих вариантах _finddata_t : The following table summarizes the variations on _finddata_t :

Структура Structure Тип времени Time type Тип размера файла File size type
_finddata_t , _wfinddata_t _finddata_t , _wfinddata_t __time64_t _fsize_t
_finddata32_t , _wfinddata32_t _finddata32_t , _wfinddata32_t __time32_t _fsize_t
__finddata64_t , __wfinddata64_t __finddata64_t , __wfinddata64_t __time64_t __int64
_finddata32i64_t , _wfinddata32i64_t _finddata32i64_t , _wfinddata32i64_t __time32_t __int64
_finddata64i32_t , _wfinddata64i32_t _finddata64i32_t , _wfinddata64i32_t __time64_t _fsize_t

_fsize_t представляет собой typedef для unsigned long (32 бита). _fsize_t is a typedef for unsigned long (32 bits).

Findfirst, findnext поиск файлов по шаблону

Время не засекал, потому что бесполезно.
Поиск как-то кешируется и в следующий раз осуществляется намного быстрее.

Суть вопроса.
Какой поиск быстрее: по всем файлам/папкам или по маске ?

Предполагаю, что поиск по маске — это поиск по всем файлам, только с фильтрафией внутри FindFirst/FindNext. Или я не прав и есть какой-то крутой механизм у них?

Поиск по маске — это функция операционной системы, и FindFirst/FindNext в обоих случаях ничего сами не фильтруют, а просто передают ей параметры твоего запроса. Насчет крутых механизмов. ну, все стандартное. Дисковый кэш — это крутой механизм?

Так ответ. Быстрее или нет? Если да, то насколько?


> Какой поиск быстрее: по всем файлам/папкам или по маске
> ?

А это от ситуации зависит, может и быстрее и медленнее. Кроме того основаная проблема это дисковые операции.

Анатолий, я не понял


> [2] DevilDevil © (10.08.09 11:28)

что быстрее или нет?

Случай 1. Фильтрация по маске осуществляется внутри FindFirst/FindNext
Происходит перебор всех файлов. Если имя файла соответствует маске, то возвращается TSearchRec.
Перебор всех файлов в таком случае будет быстрее, т.к. не происходит фильтрации

Случай 2. Фильтрация по маске осуществляется каким-то мега супеп пупер алгоритмом, позволяющим не проходить по всем файлам.
В этом случае поиск будет быстрее.

Вопрос. Как осуществляется поиск: первым случаем или вторым?

> DevilDevil (10.08.2009 11:44:06) [6]

Я уже ответил, что не понятного?

От какой ситуации зависит?
От чего?
Каким способом осуществляется поиск: первым или вторым?

P.S. моя задача — максимально быстрый поиск jpg, jpe, jpeg, jfif, bmp — файлов.
Стараюсь понять, как сделать быстрее.

> DevilDevil (10.08.2009 11:58:08) [8]

От количества файлов попадающих под условия, худший случай маски *.* — будут обработаны все файлы. Лучший случай, когда под условие попадает только один файл, с маской file.ext

Твоя задача подразумевает сделать это за один проход или за пять?

ЗЫ: без маски FindFirst не работает, никогда.


DevilDevil © (10.08.09 11:58) [8]
> P.S. моя задача — максимально быстрый поиск jpg, jpe, jpeg,
> jfif, bmp — файлов.
> Стараюсь понять, как сделать быстрее

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

>Anatoly Podgoretsky
>ЗЫ: без маски FindFirst не работает, никогда.

Верно. Но маска *.* широко распространена и вполне может оптимизироваться ОС, не используя фильтрацию вообще.

>Сам же убедился, что особой разницы нет.
не убедился
не производил замеров времени.

>Быстрый поиск осуществляется предварительным индексированием
?

Ну хорошо
А как сформировать маску из нескольких расширений

Ну для jpg знаю — *.jpg. А для нескольких?

> DevilDevil (10.08.2009 14:07:12) [12]

Разбери исходник этих функций и убедишься, что не имеет значения, используешь ты маску «*.jpg» или «*.*».

>qwer_qwer
у тебя есть исходник FindFirst и FindNext ?

>Palladin ©
>Anatoly Podgoretsky ©

Dir + «\*.jpg *.jpe *.jpeg *.jfif *.bmp ?

у тебя есть исходник FindFirst и FindNext ?

Он у всех есть.
А вот FindFirstFile — не у всех


> [16] DevilDevil © (10.08.09 14:48)

ты читать не умеешь? ах ну конечно, я забыл F1 добавить. у всех со словом ExtractFileExt идут именно такие ассоциации.

>Palladin ©
Я не понял, что ты имел ввиду.
В помощи не нашёл

Мне бы пример маски на несколько разрешений.
Больше ничего не надо

> DevilDevil (10.08.2009 15:07:19) [19]

interface
uses
SysUtils, Classes, ShellAPI;

Directory — папка в которой нужо искать.
ScanSubFolders — флаг поиска в подпапках.
Strings — результат поиска. Объект должен быть создан.
Extension — поиск файлов с определенным расширением,
если ограничений нет — оставьте пустым.
FileName — поиск файлов с определенным именем,
если ограничений на имя нет — оставьте пустым.
RecursionCount — бесполезный параметр, задайте 0.
SeachOnlyDirectorys — искать только папки.>
procedure ScanDirectory(Directory: string; ScanSubFolders: Boolean;
Strings: TStrings; Extension: string; FileName: string;
RecursionCount: Integer; SeachOnlyDirectorys: Boolean = False);

<Скопировать папку с подпапками и другими потрахами.>
procedure CopyDirectoryTree(AHandle: THandle;
AFromDir, AToDir: string);
<Скопировать файл.>
procedure CopyFile(AHandle: THandle;
AFromFileName, AToFileName: string);
implementation

procedure ScanDirectory(Directory: string; ScanSubFolders: Boolean;
Strings: TStrings; Extension: string; FileName: string;
RecursionCount: Integer; SeachOnlyDirectorys: Boolean = False);
var
CurrentFile: TSearchRec;
begin
Directory := IncludeTrailingPathDelimiter(Directory);
if Assigned(Strings) and DirectoryExists(Directory) then
begin
try
if FindFirst(Directory + «*.*», faAnyFile, CurrentFile) = 0 then
begin
repeat
if (CurrentFile.Name <> «.») and (CurrentFile.Name <> «..») then
begin
if ((CurrentFile.Attr and faDirectory) <> 0) and ScanSubFolders then
ScanDirectory(Directory+CurrentFile.Name, ScanSubFolders, Strings,
Extension, FileName, RecursionCount + 1, SeachOnlyDirectorys);
if (Extension = «») or (ExtractFileExt(CurrentFile.Name) = Extension) then
if (FileName = «») or (FileName = CurrentFile.Name) then
if (not SeachOnlyDirectorys) or ((CurrentFile.Attr and faDirectory) <> 0) then
Strings.Add(Directory+CurrentFile.Name)
end;
until FindNext(CurrentFile) <> 0;
end;
finally
FindClose(CurrentFile);
end;
end;
end;

procedure CopyDirectoryTree(AHandle: THandle; AFromDir,
AToDir: string);
var
SHFileOpStruct: TSHFileOpStruct;
begin
with SHFileOpStruct do
begin
Wnd := AHandle;
wFunc := FO_COPY;
<Про #0 не надо забывать.>
pFrom := PChar(AFromDir+ #0);
pTo := PChar(AToDir+ #0);
fFlags := FOF_NOCONFIRMATION;
fAnyOperationsAborted := False;
hNameMappings := nil;
lpszProgressTitle := nil;
end;
SHFileOperation(SHFileOpStruct);
end;

procedure CopyFile(AHandle: THandle;
AFromFileName, AToFileName: string);
begin
CopyDirectoryTree(AHandle, AFromFileName,
AToFileName);
end;

Добавить цикл для нескольких расширений, я думаю, труда не составит?

Хороший пример
Как раз показывает то, что вы перебираете все файлы
А я говорю, что быстрее в FindFirst задать маску
В этом вопрос

мда. это не лечится.

Это перебор всех файлов.
Поиск по маске «все мои картинки» (какой бы она ни была) — это тоже перебор ВСЕХ файлов.

И другого просто быть не может.

>Медвежонок Пятачок
это ты не лечишься

> Поиск по маске «все мои картинки» (какой бы она ни была)
> — это тоже перебор ВСЕХ файлов.
> И другого просто быть не может.

Все согласны? Нет способа задать маску на несколько разширений?

Если да, то не быстрее будет 5 поисков: каждый по своему разширению?


> DevilDevil © (10.08.09 15:16) [22]

> Как раз показывает то, что вы перебираете все файлы
> А я говорю, что быстрее в FindFirst задать маску

Во-первых, задать несколько масок так и не удасться.
Во-вторых, в скорости проверки на соответствие имени маске
можно тягаться и с MS, хотя, конечно, нижний предел определен
скоростью дисковых операций.

Kolan © (10.08.09 15:13) [21]

То ли Ленина не уважаешь, то ли не копированием, а чем-то другим занимаешься.

Все согласны? Нет способа задать маску на несколько разширений?

Ты на самом деле думаешь, что виндоус встретив твою маску не будет перебирать ВСЕ файлы, а сразу соединится с Центральным Мозгом Галактики, который сообщит ей готовый список файлов в твоем каталоге, которые удовлетворяют маске?

> DevilDevil (10.08.2009 16:02:26) [26]

А рамках FindFirst нет возможностей, используй MatchesMask и небольшой цикл.

> RecursionCount — бесполезный параметр, задайте 0.

:)

Про Ленина — не понял. :)


> Игорь Шевченко © (10.08.09 16:06) [28]

> То ли Ленина не уважаешь

Игорь, sorry, напомни, please, где тут про ВИЛ?
Оговорку по фрейду отметили (один пих на уме:), но не догнали :)

Всем участникам спасибо.
особенно Anatoly Podgoretsky

Kolan © (10.08.09 16:22) [32]
Leonid Troyanovsky © (10.08.09 16:22) [33]

Да будь я негром преклонным годов,
и то без унынья и лени
Я русский бы выучил только за то.

> Kolan © (10.08.09 15:13) [21]

Если я правильно отследил отступы, в коде есть неточность:
FindClose может выполниться при неуспешном FindFirst.

Быстрее всего разбирать mft руками. Пользую и всем рекомендую everything. Ищет практически моментально среди 750 тыс файлов на моём венике. Думаю, что mft расковыривает.

Findfirst, findnext список файлов, но не каталогов.

следующий код перечисляет файлы, но не каталоги

5 ответов

18 Решение François [2009-09-25 20:30:00]

  • Вам не нужно исключать каталоги, которые вы, к сожалению, делаете с вашим (-faDirectory)
  • Вы должны позвонить FindClose, когда закончите.
  • Вам нужно выполнить цикл, если вы хотите найти все в каталоге

Параметр Attr указывает специальные файлы для включения дополнительно для всех нормальных файлов.

Другими словами, FindFirst() всегда возвращает нормальные файлы, независимо от любых указанных вами критериев фильтрации. Параметр Attr включает только другие типы атрибутов в базовый фильтр. Вам нужно проверить поле TSearchRec.Attr , чтобы определить, является ли зарегистрированная запись фактическим файлом или каталогом, например:

Если вы реализуете цикл рекурсивного поиска, обязательно игнорируйте «.». и «..», иначе ваш цикл будет откладываться неопределенно:

4 devio [2009-09-25 20:15:00]

Вы явно исключили каталоги, указав «- faDirectory» в параметре flags.

Как насчет findfirst (‘c:\test\*’, faanyfile, rec);//не faanyfile-fadirectory

-2 Joe [2009-09-25 20:01:00]

Если вам нужны все файлы и каталоги, просто перейдите в каталог faDirectory, чтобы найти first. Он уже вернет вам файлы.

FindFirstFile/FindNextFile и русские символы

Писал простой рекурсивный поиск файлов по маске. С английскими символами всё работает прекрасно, но как только программа встречает русский, то передаёт в буфер мусор и функция вылетает. Пытался взять код с этого сайта (с похожего вопроса), но он также не работает с русскими символами. Пример кода:

функция для поиска файлов в текущей папке

и рекурсивная функция для поиска папок и вызова первой функции

Ошибка из за того, что в функцию передаются отрицательные значения (русские буквы). Как правильно передать строку в качестве аргумента в данном случае?

1 ответ 1

Подозреваю что у вас отключен UNICODE. Ядро Windows работает с юникодом. WinAPI для char-ов конвертирует входные wchar-ы в char-ы, вызывает функции ядра, получает результат в wchar-ах и снова конвертирует их в char-ы. Таким образом ваша функция будет интенсивно заниматься онанизмом: выделять/освобождать память для промежуточных результатов и гонять туда-сюда char-ы в wchar-ы.

Но вам видимо этого мало, и решили для увеличения объема онанизма привлечь ещё и стринги. Которые тоже при каждом чихе занимаются выделением/освобождением памяти, и возможно тоже всякими конвертациями char-ов/wchar-ов. Непонимание русских символов заложено именно в них. Просто WinAPI работает без проблем.

Возьмите один буфер достаточного объема, и напишите одну функцию. Всё будет работать.

Для ANSI версии буфер (максимальная длина пути) составляет MAX_PATH. Для UNICODE 32767 символов. Но чтобы использовать «длинный путь» он должен начинаться с четырех символьного префикса «\\\\?\\» . Например L»\\\\?\\C:\\и так далее» .


Поиск файлов в Linux. Утилита find

Введение

Одна из наиболее распространенных проблем, с которыми сталкиваются пользователи, впервые работающие с Linux — поиск нужных файлов. В данном руководстве рассмотрено использование команды find, которая позволяет решить эту проблему и осуществлять поиск файлов с различными фильтрами и параметрами.

Поиск по имени

Это наиболее очевидный способ поиска файлов. Для поиска по имени введите:

Этот запрос будет чувствительным к регистру, то есть “file” и “File” будут восприниматься как разные имена.

Для поиска по имени без учёта регистра введите:

Если вам требуется найти все файлы, не соответствующие определенному шаблону, можно инвертировать поиск при помощи параметра “-not” или “!”. При использовании “!” нужно экранировать символ, чтобы bash не попытался интерпретировать его до начала работы find:

Поиск по типу

Вы можете указать тип файлов, которые вам нужно найти, при помощи параметра «-type» Это работает следующим образом:

Вот наиболее распространенные дескрипторы типа:

f: обычный файл
d: директория
l: символическая ссылка
c: символьные устройства
b: блочные устройства

Например, если нам нужно найти все символьные устройства в системе, можно выполнить следующую команду:

А так мы можем выполнить поиск всех файлов, которые заканчиваются на «.conf»:

Поиск по времени и размеру

Find предоставляет ряд способов фильтрации результатов по размеру и времени.

Поиск по размеру

Фильтрация по размеру осуществляется при помощи параметра «-size».

После значения размера нужно указать суффикс, обозначающий единицы измерения. Вот несколько наиболее распространенных вариантов:

c: байты
k: килобайты
M: мегабайты
G: гигабайты
b: блоки по 512 байт

Чтобы найти все файлы с размером ровно 100 байт, введите:

Для поиска всех файлов меньше 100 байт мы можем воспользоваться следующей формой:

Для поиска файлов больше 500 мегабайт можно использовать следующую команду:

Поиск по время

Linux хранит данные о времени доступа, времени модификации и времени изменения.

  • Время доступа: время последнего чтения файла или записи в него.
  • Время модификации: время последнего изменения содержимого файла.
  • Время изменения: время последнего изменения метаданных в индексном узле (inode) файла.

Для фильтрации по этим значениям мы можем использовать параметры «-atime», «-mtime» и «-ctime», соответственно, а также символы плюса и минуса для поиска файлов с более ранним или поздним временем, аналогично фильтрации по размеру.

Значение этих параметров указывает, на сколько дней назад нужно осуществлять поиск.

Для поиска файлов, содержимое которых было изменено вчера, введите:

Если нам нужны файлы, к которым осуществлялся доступ вчера и позже, можно воспользоваться командой:

Чтобы получить файлы, метаданные которых были изменены более трёх дней назад, воспользуйтесь следующей командой:

Также существуют дополнительные параметры, которые позволяют указывать минуты вместо дней. Эта команда выдает файлы, измененные за последнюю минуту:

Кроме того, find может выполнять сравнение с заданным файлом и выводить все файлы новее:

Поиск по владельцу и разрешениям

Используя параметры «-user» и «-group», можно осуществлять поиск файлов по владельцу или группе, соответственно. Чтобы найти файл пользователя «syslog», нужно ввести:

Аналогично можно задать поиск файлов группы «shadow»:

Также можно искать файлы с определенными разрешениями.

Если нам нужно соответствие точному набору разрешений, используется следующая форма:

При необходимости найти все файлы с разрешениями не ниже указанных нужно ввести:

Этому критерию будут соответствовать все файлы с дополнительными разрешениями. Например, в данном случае ему будет соответствовать файл с разрешениями «744».

Фильтрация по глубине

Для этого раздела нам потребуется создать во временной директории трехуровневую структуру директорий с десятью директориями на первом уровне. В каждой директории (включая временную) будет десять поддиректорий и десять файлов.

Создадим структуру выполнением следующих команд:

Для проверки структуры можно воспользоваться командами ls и cd. Разобравшись в организации нужно вернуться в тестовую директорию:

Теперь попробуем найти в этой структуре конкретные файлы. Начнем с примера обычного поиска по имени:

Результатов очень много. Если мы переведем вывод на счётчик, мы увидим, что всего таких файлов 1111:

В большинстве случаев эти результаты избыточны. Давайте попробуем сузить поиск.

Можно задать максимальную глубину поиска в директории поиска верхнего уровня:

Чтобы найти «file1» только в директориях «level1» и выше, нужно указать максимальную глубину, равную 2 (1 для директории верхнего уровня и 1 для директорий уровня 1):

С этим списком справиться гораздо проще.

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

Так мы можем найти все файлы на концах ветвей дерева директорий:

. . .
Из-за нашей древовидной структуры снова будет выведено большое количество результатов (1000).

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

Выполнение команд над результатами

Над любыми файлами, которые вы найдете командой find, можно выполнить произвольную дополнительную команду при помощи параметра «-exec». Это выполняется следующим образом:

Фигурные скобки «<>» используются в качестве заполнителя места для файлов, найденных командой find. Обратный слэш и точка с запятой «\;» используются для того, чтобы указать find, где кончается команда.

Например, мы можем найти файлы из предыдущего раздела с разрешениями “644” и изменить разрешения на “664”:

Затем мы можем изменить разрешения для директории следующим образом:

Если вам нужно объединить различные результаты, вы можете воспользоваться командами «-and» или «-or». «-and» предполагается по умолчанию и опускается.

Заключение

Find — полезная команда, возможности которой можно расширить, объединяя ее с другими утилитами. Можно поэкспериментировать с фильтрацией при помощи команд wc, sort и grep.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Программный поиск файлов на Delphi (исходники)

В этом уроке мы с вами ознакомимся с основными принципами программной организации поиска файлов. Для начала определимся, зачем нам это может быть нужно. Например, вам нужно при запуске программы на выполнение просканировать определенный каталог на присутствие DOC файлов, и при наличии таковых открыть их на редактирование или напечатать. А как вам такая идея: фоновый поиск EXE файла в сети, и при обнаружении новой версии, автоматическое обновление.

Многим известны программы, где можно искать файлы, правила поиска файла. Файлы можно искать как с файловых командирах (нортон, волков, дос навигатор, фар), так в любой операционной системе. В операционной системе windows диалоговое окно поиска файла вызывается «Пуск» — «Поиск» — «Файлы и папки». В открывшимся окне необходимо задать условие искомого файла (название, маска) и путь начального поиска (каталог). На других вкладках этого диалогового окна можно расширить возможности поиска по дате изменения, по содержащемуся тексту, по размеру.

Вспомним правила поиска файлов. Вы можете задать как имя искомого файла, так и его маску, если название неизвестно или необходимо найти несколько. Т.е. применяя специальный шаблон поиска, вы можете организовать условия выборки найденных файлов. Сразу оговорюсь, что поиск можно применять как к файлам, так и к каталогам. Будем их называть элементами файловой системы. В шаблон маски искомых элементов может входить:

  1. Буквы и цифры в названии и расширении.
  2. Символ * (звездочка, математический знак «умножить»), заменяющий любое количество всевозможных букв и цифр в названии или расширении.
  3. Символ ? (знак вопроса), заменяющий одну букву или цифру в названии или расширении искомого элемента.

Например, вы ищите все текстовые файлы с расширением TXT. В поле имени искомого файла вам нужно ввести «*.TXT» (пишется без кавычек) и система найдет все такие файлы в указанном диске или каталоге. Если вам надо найти все файлы с названием semen, то в поле поиска файла нужно ввести «semen.*». Если вам нужно найти элементы с третьей буквой k и с первой буквой t в расширении, то вводите «??k*.t*». Здесь знак вопроса указывает на любой символ, третьим символом по порядку идет буква k, далее название файла (каталога) может состоять из любого количества букв и цифр, указываем звездочку. В расширении первая буква t, дальше следует любое расширение.
Примечание: файлы и каталоги в операционной системе windows ищутся без учета регистра, т.е. строчние и прописные буквы не различаются.

Теперь рассмотрим программный поиск файлов с помощью языка программирования object pascal.

Вся организация цикла поиска, а именно это и есть цикл с продолжением поиска, сводится к:

  1. Задание условий поиска. Это каталог и маска искомого элемента или элементов, атрибуты элемента(ов). При задании условий поиска сразу происходит поиск первого подходящего под условие. Это функция FindFirst.
  2. Продолжение поиска следующего элемента по заданным в первом пункте условиям. Это функция FindNext и она может вызываться сколько угодно раз, пока все файлы и каталоги, удовлетворяющие условию, не будут найдены.
  3. Закрытие поиска и освобождение памяти, выделяемую системой под поиск. Команда FindClose.

Функция FindFirst

где: Каталог для поиска и маска искомого элемента — строковая величина, имеющая тип String, может, например, содержать ‘c:\*.*’ — все элементы в корне диска С. Обратите внимание, что указывается полный путь для поиска.

Атрибуты искомого элемента это пользовательские или системные атрибуты, которые может иметь файл (каталог, метка диска). Вот их перечень:

  • faReadOnly — Файлы «только чтение». Такой атрибут устанавливается на файлы, которые не рекомендовано изменять, удалять. Такой атрибут имеют файлы, например, записанные на компакт-дисках.
  • faHidden — Скрытые файлы. При обычных установках браузера и командира эти файлы невидимы.
  • faSysFile — Системные файлы.
  • faVolumeID — Файл метки диска. Такой элемент в своем имени имеет название диска (максимум 11 символов).
  • faDirectory — Атрибут признака каталога.
  • faArchive — Обычный файл. По умолчанию устанавливается на заново создаваемых файлах.
  • faAnyFile — Если установить в качестве атрибута искомых элементов, то будет произведен поиск по всем вышесказанным атрибутам.

Если вам нужно искать только элементы, имеющие атрибут «каталог» и «скрытый», то можно применить знак математического сложения, например faDirectory + faHidden.

Поисковая переменная имеет тип TSearchRec. В нее, при успешном результате поиска, будет занесены все необходимые данные о найденном файловом элементе.

Поскольку FindFirst является функцией, то она должна сама возвращать некоторое значение. Это значение имеет тип Integer и означает результат поиска файла (код ошибки поиска). Если файл найден, то принимает нулевое значение.

Функция FindNext

Эта функция продолжает поиск, заданный в функции FindNext. Возвращает значение результата поиска (нулевое в случае успешного поиска).

Процедура FindClose

Закрывает поиск и освобождает память, выделенную системой под поиск.

Теперь рассмотрим пример. Допустим, нам надо найти все файлы и каталоги в каталоге DELPHI, находящийся на диске C:. В дальнейшем, вы можете самостоятельно, изменяя маску, менять условия поиска. Для формы с компонентом ListBox1 и кнопкой Button1 реакция на OnClick по кнопке:

Представленный пример кода, в принципе, является основой для организации более углубленного поиска, поиска файлов по времени создания, по содержащимся словам. Если вы запустите эту программу на выполнение, то при нажатии на кнопку Button1 вы увидите в списке в первой и второй строке элементы «.» и «..». Это элементы, имеющие атрибут «каталог». Первый содержит связь с корневым каталогом диска, второй содержит связь к каталогом верхнего уровня. Со вторым вы встречаетесь в дисковых командных оболочках, например нортон, когда выбираете каталог «..» и нажимаете на «ввод». Тем самым вы попадаете в каталог на уровень выше. Естественно, в нашей поисковой программе такие элементы не надо вносить в список, поэтому мы игнорируем их нахождение. Исправляем процедуру нажатия на кнопку Button1:

В этом случае, при нахождении каталога с именем «.» или с именем «..» программа продолжит обработку цикла поиска без вывода найденного имени элемента в компонент списка ListBox1.

Теперь рассмотрим тип TSearchRec. Он имеет в себе несколько полезных свойств:

  • Name — название найденного каталога (файла);
  • Size — размер файла в байтах;
  • Attr — атрибуты каталога (файла);
  • Time — упакованное значение времени и даты создания каталога (файла).

Все вышеперечисленные свойства мы уже рассмотрели или они понятны сразу, за исключением свойства Time. Оно имеет тип Integer и содержит в себе упакованное значение даты и времени создания файла. Распаковка производится с помощью функции FileDateToDateTime, которая в результате возвращает значение даты и времени.
Теперь добавим в нашу форму компонент DateTimePicher1 (страница Win32) и допишем несколько строк.

Как вы уже заметили, мы отбираем файлы и каталоги по дате создания, начиная с указанной в компоненте DateTimePicker1.

Теперь попробуем организовать поиск файлов во всех вложенных каталогах. Это не так просто, как может показаться на первый взгляд. Нам придется вручную организовывать весь цикл входа-выхода из каталога, перебор файлов. Немного сложноватый материал, но возможно те из вас, кто уже работал с языком программирования pascal или другим, знакомы с технологией многократности и многовложенности использования одного и того же программного кода. Коротко объясню алгоритм работы такой программы.

  1. Задание начальных условий поиска, поиск первого элемента.
  2. Если найден файл, то выводим его и соответственно обрабатываем (выводим в список, открываем, удаляем и т.п.).
  3. Если найден каталог, то начинаем новую процедуру поиска. Но программный код остается прежним. Мы просто заново вызываем и входим в эту же процедуру поиска.
  4. Обрабатываем таким же образом все вложенные в этот каталог файлы и каталоги (начинаем новый поиск в обнаруженном каталоге).
  5. Если элементов во вложенном каталоге больше нет, то обработка процедуры поиска в нем завершается, и мы выходим из нее. При этом мы оказываемся в том же месте, откуда и вызвали эту процедуру. Но она была вызвана из этой же процедуры. Поэтому программа продолжает свое выполнение дальше с момента возврата.

Таким образом, сколько витков программа наматывает на так называемый клубок, столько витков она и размотает. Программа на выполнении проходит все дерево вложенных каталогов, выполняя один и тот же кусок программного кода! И при этом данные условий поиска не перепутываются, и для каждой уникальной процедуры они сохраняются.

Рассмотрим пример. Создайте новый проект. Для создания отдельной процедуры поиска нам нужно объявить ее в соответствующем разделе (создаем ее вручную, поэтому и самостоятельно объявляем).

В разделе public пишем строку:

А в разделе кода программы, до слова «end.» вставляем пустой каркас процедуры

На форму вставляем компонент списка ListBox1, Button1, Edit1. Для компонента Edit1 свойство Text устанавливаем в «c:\delphi\». Обратите внимание на последний символ, знак «\», присутствие которого в начальном пути поиска обязательно. Дальше процедура OnClick для кнопки Button1 выглядит следующим образом:

Созданная нами вручную процедура поиска:

Если вы в компоненте Edit1 в качестве начального условия поиска файлов зададите корневую папку диска, например «С:\», то вы получите полный перечень всех файлов на данном диске. Обратите внимание на скорость поиска файлов и скорость работы вашей программы.

Команда find в Linux

Очень важно уметь вовремя и очень быстро найти нужную информацию в системе. Конечно, все современные файловые менеджеры предлагают отличные функции поиска, но им не сравнится с поиском в терминале Linux. Он намного эффективнее и гибче обычного поиска, вы можете искать файлы не только по имени, но и по дате добавления, содержимому, а также использовать для поиска регулярные выражения. Кроме того, с найденными файлами можно сразу же выполнять необходимые действия.

В этой статье мы поговорим о поиске с помощью очень мощной команды find Linux, подробно разберем ее синтаксис, опции и рассмотрим несколько примеров.

Основная информация о Find

Find — это одна из наиболее важных и часто используемых утилит системы Linux. Это команда для поиска файлов и каталогов на основе специальных условий. Ее можно использовать в различных обстоятельствах, например, для поиска файлов по разрешениям, владельцам, группам, типу, размеру и другим подобным критериям.

Утилита find предустановлена по умолчанию во всех Linux дистрибутивах, поэтому вам не нужно будет устанавливать никаких дополнительных пакетов. Это очень важная находка для тех, кто хочет использовать командную строку наиболее эффективно.

Команда find имеет такой синтаксис:

find [ папка] [ параметры] критерий шаблон [действие]

Папка — каталог в котором будем искать

Параметры — дополнительные параметры, например, глубина поиска, и т д

Критерий — по какому критерию будем искать: имя, дата создания, права, владелец и т д.

Шаблон — непосредственно значение по которому будем отбирать файлы.

Основные параметры команды find

Я не буду перечислять здесь все параметры, рассмотрим только самые полезные.

  • -P никогда не открывать символические ссылки
  • -L — получает информацию о файлах по символическим ссылкам. Важно для дальнейшей обработки, чтобы обрабатывалась не ссылка, а сам файл.
  • -maxdepth — максимальная глубина поиска по подкаталогам, для поиска только в текущем каталоге установите 1.
  • -depth — искать сначала в текущем каталоге, а потом в подкаталогах
  • -mount искать файлы только в этой файловой системе.
  • -version — показать версию утилиты find
  • -print — выводить полные имена файлов
  • -type f — искать только файлы
  • -type d — поиск папки в Linux

Критерии

Критериев у команды find в Linux очень много, и мы опять же рассмотрим только основные.

  • -name — поиск файлов по имени
  • -perm — поиск файлов в Linux по режиму доступа
  • -user — поиск файлов по владельцу
  • -group — поиск по группе
  • -mtime — поиск по времени модификации файла
  • -atime — поиск файлов по дате последнего чтения
  • -nogroup — поиск файлов, не принадлежащих ни одной группе
  • -nouser — поиск файлов без владельцев
  • -newer — найти файлы новее чем указанный
  • -size — поиск файлов в Linux по их размеру

Примеры использования

А теперь давайте рассмотрим примеры find, чтобы вы лучше поняли, как использовать эту утилиту.

1. Поиск всех файлов

Показать все файлы в текущей директории:

2. Поиск файлов в определенной папке

Показать все файлы в указанной директории:

Искать файлы по имени в текущей папке:

Не учитывать регистр при поиске по имени:


find . -iname «test*»

3. Ограничение глубины поиска

Поиска файлов по имени в Linux только в этой папке:

find . -maxdepth 1 -name «*.php»

4. Инвертирование шаблона

Найти файлы, которые не соответствуют шаблону:

find . -not -name «test*»

5. Несколько критериев

Поиск командой find в Linux по нескольким критериям, с оператором исключения:

find . -name «test» -not -name «*.php»

Найдет все файлы, начинающиеся на test, но без расширения php. А теперь рассмотрим оператор ИЛИ:

find -name «*.html» -o -name «*.php»

6. Несколько каталогов

Искать в двух каталогах одновременно:

find ./test ./test2 -type f -name «*.c»

7. Поиск скрытых файлов

Найти скрытые файлы:

8. Поиск по разрешениям

Найти файлы с определенной маской прав, например, 0664:

find . type f -perm 0664

Найти файлы с установленным флагом suid/guid:

find / -perm 2644

find / -maxdepth 2 -perm /u=s

Поиск файлов только для чтения:

find /etc -maxdepth 1 -perm /u=r

Найти только исполняемые файлы:

find /bin -maxdepth 2 -perm /a=x

9. Поиск файлов по группах и пользователях

Найти все файлы, принадлежащие пользователю:

find . -user sergiy

Поиск файлов в Linux принадлежащих группе:

find /var/www -group developer

10. Поиск по дате модификации

Поиск файлов по дате в Linux осуществляется с помощью параметра mtime. Найти все файлы модифицированные 50 дней назад:

Поиск файлов в Linux открытых N дней назад:

Найти все файлы, модифицированные между 50 и 100 дней назад:

find / -mtime +50 –mtime -100

Найти файлы измененные в течении часа:

11. Поиск файлов по размеру

Найти все файлы размером 50 мегабайт:

От пятидесяти до ста мегабайт:

find / -size +50M -size -100M

Найти самые маленькие файлы:

find . -type f -exec ls -s <> \; | sort -n -r | head -5

find . -type f -exec ls -s <> \; | sort -n | head -5

12. Поиск пустых файлов и папок

find /tmp -type f -empty

13. Действия с найденными файлами

Для выполнения произвольных команд для найденных файлов используется опция -exec. Например, выполнить ls для получения подробной информации о каждом файле:

find . -exec ls -ld <> \;

Удалить все текстовые файлы в tmp

find /tmp -type f -name «*.txt» -exec rm -f <> \;

Удалить все файлы больше 100 мегабайт:

find /home/bob/dir -type f -name *.log -size +10M -exec rm -f <> \;

Выводы

Вот и подошла к концу эта небольшая статья, в которой была рассмотрена команда find. Как видите, это одна из наиболее важных команд терминала Linux, позволяющая очень легко получить список нужных файлов. Ее желательно знать всем системным администраторам. Если вам нужно искать именно по содержимому файлов, то лучше использовать команду grep.

Findfirst, findnext поиск файлов по шаблону

Время не засекал, потому что бесполезно.
Поиск как-то кешируется и в следующий раз осуществляется намного быстрее.

Суть вопроса.
Какой поиск быстрее: по всем файлам/папкам или по маске ?

Предполагаю, что поиск по маске — это поиск по всем файлам, только с фильтрафией внутри FindFirst/FindNext. Или я не прав и есть какой-то крутой механизм у них?

Поиск по маске — это функция операционной системы, и FindFirst/FindNext в обоих случаях ничего сами не фильтруют, а просто передают ей параметры твоего запроса. Насчет крутых механизмов. ну, все стандартное. Дисковый кэш — это крутой механизм?

Так ответ. Быстрее или нет? Если да, то насколько?


> Какой поиск быстрее: по всем файлам/папкам или по маске
> ?

А это от ситуации зависит, может и быстрее и медленнее. Кроме того основаная проблема это дисковые операции.

Анатолий, я не понял


> [2] DevilDevil © (10.08.09 11:28)

что быстрее или нет?

Случай 1. Фильтрация по маске осуществляется внутри FindFirst/FindNext
Происходит перебор всех файлов. Если имя файла соответствует маске, то возвращается TSearchRec.
Перебор всех файлов в таком случае будет быстрее, т.к. не происходит фильтрации

Случай 2. Фильтрация по маске осуществляется каким-то мега супеп пупер алгоритмом, позволяющим не проходить по всем файлам.
В этом случае поиск будет быстрее.

Вопрос. Как осуществляется поиск: первым случаем или вторым?

> DevilDevil (10.08.2009 11:44:06) [6]

Я уже ответил, что не понятного?

От какой ситуации зависит?
От чего?
Каким способом осуществляется поиск: первым или вторым?

P.S. моя задача — максимально быстрый поиск jpg, jpe, jpeg, jfif, bmp — файлов.
Стараюсь понять, как сделать быстрее.

> DevilDevil (10.08.2009 11:58:08) [8]

От количества файлов попадающих под условия, худший случай маски *.* — будут обработаны все файлы. Лучший случай, когда под условие попадает только один файл, с маской file.ext

Твоя задача подразумевает сделать это за один проход или за пять?

ЗЫ: без маски FindFirst не работает, никогда.


DevilDevil © (10.08.09 11:58) [8]
> P.S. моя задача — максимально быстрый поиск jpg, jpe, jpeg,
> jfif, bmp — файлов.
> Стараюсь понять, как сделать быстрее

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

>Anatoly Podgoretsky
>ЗЫ: без маски FindFirst не работает, никогда.

Верно. Но маска *.* широко распространена и вполне может оптимизироваться ОС, не используя фильтрацию вообще.

>Сам же убедился, что особой разницы нет.
не убедился
не производил замеров времени.

>Быстрый поиск осуществляется предварительным индексированием
?

Ну хорошо
А как сформировать маску из нескольких расширений

Ну для jpg знаю — *.jpg. А для нескольких?

> DevilDevil (10.08.2009 14:07:12) [12]

Разбери исходник этих функций и убедишься, что не имеет значения, используешь ты маску «*.jpg» или «*.*».

>qwer_qwer
у тебя есть исходник FindFirst и FindNext ?

>Palladin ©
>Anatoly Podgoretsky ©

Dir + «\*.jpg *.jpe *.jpeg *.jfif *.bmp ?

у тебя есть исходник FindFirst и FindNext ?

Он у всех есть.
А вот FindFirstFile — не у всех


> [16] DevilDevil © (10.08.09 14:48)

ты читать не умеешь? ах ну конечно, я забыл F1 добавить. у всех со словом ExtractFileExt идут именно такие ассоциации.

>Palladin ©
Я не понял, что ты имел ввиду.
В помощи не нашёл

Мне бы пример маски на несколько разрешений.
Больше ничего не надо

> DevilDevil (10.08.2009 15:07:19) [19]

interface
uses
SysUtils, Classes, ShellAPI;

Directory — папка в которой нужо искать.
ScanSubFolders — флаг поиска в подпапках.
Strings — результат поиска. Объект должен быть создан.
Extension — поиск файлов с определенным расширением,
если ограничений нет — оставьте пустым.
FileName — поиск файлов с определенным именем,
если ограничений на имя нет — оставьте пустым.
RecursionCount — бесполезный параметр, задайте 0.
SeachOnlyDirectorys — искать только папки.>
procedure ScanDirectory(Directory: string; ScanSubFolders: Boolean;
Strings: TStrings; Extension: string; FileName: string;
RecursionCount: Integer; SeachOnlyDirectorys: Boolean = False);

<Скопировать папку с подпапками и другими потрахами.>
procedure CopyDirectoryTree(AHandle: THandle;
AFromDir, AToDir: string);
<Скопировать файл.>
procedure CopyFile(AHandle: THandle;
AFromFileName, AToFileName: string);
implementation

procedure ScanDirectory(Directory: string; ScanSubFolders: Boolean;
Strings: TStrings; Extension: string; FileName: string;
RecursionCount: Integer; SeachOnlyDirectorys: Boolean = False);
var
CurrentFile: TSearchRec;
begin
Directory := IncludeTrailingPathDelimiter(Directory);
if Assigned(Strings) and DirectoryExists(Directory) then
begin
try
if FindFirst(Directory + «*.*», faAnyFile, CurrentFile) = 0 then
begin
repeat
if (CurrentFile.Name <> «.») and (CurrentFile.Name <> «..») then
begin
if ((CurrentFile.Attr and faDirectory) <> 0) and ScanSubFolders then
ScanDirectory(Directory+CurrentFile.Name, ScanSubFolders, Strings,
Extension, FileName, RecursionCount + 1, SeachOnlyDirectorys);
if (Extension = «») or (ExtractFileExt(CurrentFile.Name) = Extension) then
if (FileName = «») or (FileName = CurrentFile.Name) then
if (not SeachOnlyDirectorys) or ((CurrentFile.Attr and faDirectory) <> 0) then
Strings.Add(Directory+CurrentFile.Name)
end;
until FindNext(CurrentFile) <> 0;
end;
finally
FindClose(CurrentFile);
end;
end;
end;

procedure CopyDirectoryTree(AHandle: THandle; AFromDir,
AToDir: string);
var
SHFileOpStruct: TSHFileOpStruct;
begin
with SHFileOpStruct do
begin
Wnd := AHandle;
wFunc := FO_COPY;
<Про #0 не надо забывать.>
pFrom := PChar(AFromDir+ #0);
pTo := PChar(AToDir+ #0);
fFlags := FOF_NOCONFIRMATION;
fAnyOperationsAborted := False;
hNameMappings := nil;
lpszProgressTitle := nil;
end;
SHFileOperation(SHFileOpStruct);
end;

procedure CopyFile(AHandle: THandle;
AFromFileName, AToFileName: string);
begin
CopyDirectoryTree(AHandle, AFromFileName,
AToFileName);
end;

Добавить цикл для нескольких расширений, я думаю, труда не составит?

Хороший пример
Как раз показывает то, что вы перебираете все файлы
А я говорю, что быстрее в FindFirst задать маску
В этом вопрос

мда. это не лечится.

Это перебор всех файлов.
Поиск по маске «все мои картинки» (какой бы она ни была) — это тоже перебор ВСЕХ файлов.

И другого просто быть не может.

>Медвежонок Пятачок
это ты не лечишься

> Поиск по маске «все мои картинки» (какой бы она ни была)
> — это тоже перебор ВСЕХ файлов.
> И другого просто быть не может.

Все согласны? Нет способа задать маску на несколько разширений?

Если да, то не быстрее будет 5 поисков: каждый по своему разширению?


> DevilDevil © (10.08.09 15:16) [22]

> Как раз показывает то, что вы перебираете все файлы
> А я говорю, что быстрее в FindFirst задать маску

Во-первых, задать несколько масок так и не удасться.
Во-вторых, в скорости проверки на соответствие имени маске
можно тягаться и с MS, хотя, конечно, нижний предел определен
скоростью дисковых операций.

Kolan © (10.08.09 15:13) [21]

То ли Ленина не уважаешь, то ли не копированием, а чем-то другим занимаешься.

Все согласны? Нет способа задать маску на несколько разширений?

Ты на самом деле думаешь, что виндоус встретив твою маску не будет перебирать ВСЕ файлы, а сразу соединится с Центральным Мозгом Галактики, который сообщит ей готовый список файлов в твоем каталоге, которые удовлетворяют маске?

> DevilDevil (10.08.2009 16:02:26) [26]

А рамках FindFirst нет возможностей, используй MatchesMask и небольшой цикл.

> RecursionCount — бесполезный параметр, задайте 0.

:)

Про Ленина — не понял. :)


> Игорь Шевченко © (10.08.09 16:06) [28]

> То ли Ленина не уважаешь

Игорь, sorry, напомни, please, где тут про ВИЛ?
Оговорку по фрейду отметили (один пих на уме:), но не догнали :)

Всем участникам спасибо.
особенно Anatoly Podgoretsky

Kolan © (10.08.09 16:22) [32]
Leonid Troyanovsky © (10.08.09 16:22) [33]

Да будь я негром преклонным годов,
и то без унынья и лени
Я русский бы выучил только за то.

> Kolan © (10.08.09 15:13) [21]

Если я правильно отследил отступы, в коде есть неточность:
FindClose может выполниться при неуспешном FindFirst.

Быстрее всего разбирать mft руками. Пользую и всем рекомендую everything. Ищет практически моментально среди 750 тыс файлов на моём венике. Думаю, что mft расковыривает.

Findfirst, findnext список файлов, но не каталогов.

следующий код перечисляет файлы, но не каталоги

5 ответов

18 Решение François [2009-09-25 20:30:00]

  • Вам не нужно исключать каталоги, которые вы, к сожалению, делаете с вашим (-faDirectory)
  • Вы должны позвонить FindClose, когда закончите.
  • Вам нужно выполнить цикл, если вы хотите найти все в каталоге

Параметр Attr указывает специальные файлы для включения дополнительно для всех нормальных файлов.

Другими словами, FindFirst() всегда возвращает нормальные файлы, независимо от любых указанных вами критериев фильтрации. Параметр Attr включает только другие типы атрибутов в базовый фильтр. Вам нужно проверить поле TSearchRec.Attr , чтобы определить, является ли зарегистрированная запись фактическим файлом или каталогом, например:

Если вы реализуете цикл рекурсивного поиска, обязательно игнорируйте «.». и «..», иначе ваш цикл будет откладываться неопределенно:

4 devio [2009-09-25 20:15:00]

Вы явно исключили каталоги, указав «- faDirectory» в параметре flags.

Как насчет findfirst (‘c:\test\*’, faanyfile, rec);//не faanyfile-fadirectory

-2 Joe [2009-09-25 20:01:00]

Если вам нужны все файлы и каталоги, просто перейдите в каталог faDirectory, чтобы найти first. Он уже вернет вам файлы.

Илон Маск рекомендует:  Asp отправка содержимого в веб обозреватель
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL