Поиск файлов в каталоге и вложенных папках

Автор bigor, 21 ноября 2023, 17:10

0 Пользователи и 1 гость просматривают эту тему.

bigor

Я правильно понимаю, что такая конструкция
sPath = sDir & GetPathSeparator()
sFolderName = Dir(sPath, 16)
Do While (sFolderName <> "")
sFileName= Dir(sPath & sFolderName & GetPathSeparator() &"*"&sExt, 0)
Do While (sFileName <> "")
    print sPath & sFolderName & GetPathSeparator() & sFileName
    sFileName=dir()
Loop
sFolderName = Dir()
Loop

работать не будет? нужно делать список вложенных папок и потом по нему проходится.
Поддержать наш форум можно здесь

mikekaganski

Цитата: bigor от 21 ноября 2023, 17:10sPath = sDir & GetPathSeparator()
sFolderName = Dir(sPath, 16)

Я бы предложил сделать рекурсивную функцию. Сначала проходитесь по текущей папке, проверяя тип следующего результата Dir с помощью GetAttr. Заносите папки в массив, а с файлами делаете, что Вам нужно (или в другой массив). Затем, после завершения поиска всех файлов, перебираете массив имён подпапок, и вызываете ту же функцию для каждой. Таким образом, всегда активен будет только один цикл по Dir.
С уважением,
Михаил Каганский

sokol92

#2
Альтернатива: getFolderContents.

Кстати: в Excel VBA Dir - "глючная" функция, как и все функции VBA для  работы с файлами (п. 3.4.)
Владимир.

economist

Зато хорошо и надежно работает для поиска файлов/папок Python из OpenOffice|LibreOffice:

from glob import glob
def browse_subdir(s):
    ''' Вернет список Файлов и список Папок по маске:          (с)economist
        browse_subdir('D:\Txt\*.txt')    # все *.txt без подкаталогов
        browse_subdir('D:\Txt\**\*.txt') # все *.txt с подкаталогами
        browse_subdir('D:\Txt\под*')     # все папки под* без подкаталогов
        browse_subdir('D:\Txt\**\под*')  # все папки под* с подкаталогами
    '''
    return glob(s, recursive=True)

Вызвать эту по сути однострочную функцию в Basic можно методом invoke(), примеры есть на Форуме.
Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...

bigor

Оказалось, что файлы нужны были только из подкаталогов, поэтому решил поэксплуатировать ScriptForge
GlobalScope.BasicLibraries.loadLibrary("ScriptForge")
sFolderName=subfolders(sDir,"???*" )
for i= 0 to ubound(sFolderName)
sFileName= Dir( sFolderName(i)&"*"&sExt, 0) ' перебор в подкаталогах
Do While (sFileName <> "") 'Пока что либо возвращается
print sFolderName(i)  & sFileName
sFileName=dir()
Loop
Next
Поддержать наш форум можно здесь

sokol92

Я когда-то тестировал быстродействие поиска файлов. Можно модифицировать тесты и сравнить эффективность вышеуказанных способов: в локальной файловой системе (Windows) и на разделяемом ресурсе (Samba / Linux).
Владимир.

bigor

#6
Стендовые испытания в папке 1117 подкаталогов в каждом по 2 файла. Т.к. файлов в папке нет, то проверку на то, что вернул getFolderContent не делал
SUB _ScrpFrg
t=timer
GlobalScope.BasicLibraries.loadLibrary("ScriptForge")
Dim f
s=""
sFolderName=subfolders("D:\test","???*" )
for i= 0 to ubound(sFolderName)
sFileName= Dir( sFolderName(i)&"*"&sExt, 0) ' перебор в подкаталогах
Do While (sFileName <> "") 'Пока что либо возвращается
s=s & chr(13) & sFileName
sFileName=dir()
Loop
Next

msgbox timer-t
end sub
средний результат 3 забегов 10 сек
Sub FolderContent_
dim str1 as string
t=timer
oFileAccess = createUnoService( "com.sun.star.ucb.SimpleFileAccess" )

for i=0 to ubound(oFileAccess.getFolderContents("D:\test",1))
str1= oFileAccess.getFolderContents("D:\test",1)(i)
for j=0 to ubound(oFileAccess.getFolderContents(str1,0))
fn=fn & chr(13) & oFileAccess.getFolderContents(str1,0)(j)
next
next

msgbox "Время прошло > " & timer-t
end sub
средний результат 3 забегов 25 сек
Поддержать наш форум можно здесь

sokol92

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

bigor

Цитата: sokol92 от 22 ноября 2023, 14:31В тесте для getFolderContents
да теперь в среднем 1 секунда
Sub FolderContent_
dim str1 as string
t=timer
oFileAccess = createUnoService( "com.sun.star.ucb.SimpleFileAccess" )
res1=oFileAccess.getFolderContents("D:\test",1)
str1=""
for i=0 to ubound(res1)
str1 = res1(i)
res2 = oFileAccess.getFolderContents(str1,0)
for j=0 to ubound(res2)
fn=fn & chr(13) & convertfromurl(res2(j))
next
next

msgbox "Время прошло > " & timer-t
msgbox fn
end sub
Поддержать наш форум можно здесь

sokol92

Если файлов много (тысячи), то конкатенация их имен в строку - не быстрое дело. Как изменится время, если просто подсчитывать количество найденных файлов?
Владимир.

bigor

Цитата: sokol92 от 22 ноября 2023, 14:52подсчитывать количество найденных файлов?
практически мгновенно. Замена конкатенации уменьшает время работы макросов примерно на 1 сек
Поддержать наш форум можно здесь

sokol92

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

Sub FolderContent_2
dim str1 as String, fn As String
Dim arr, ind As Long
t=timer
oFileAccess = createUnoService( "com.sun.star.ucb.SimpleFileAccess" )
res1=oFileAccess.getFolderContents("C:\temp\temp7",1)

ind=-1
ReDim arr(999)

for i=0 to ubound(res1)
str1 = res1(i)
res2 = oFileAccess.getFolderContents(str1,0)
for j=0 to ubound(res2)
  ind=ind+1
  If ind>UBound(arr) Then
    ReDim Preserve arr(2 * Ubound(arr))
  End If 
  arr(ind)=convertfromurl(res2(j))
next
next

If ind>0 Then
  ReDim Preserve arr(ind)
  fn=Join(arr, Chr(13))
End iF 

msgbox "Время прошло > " & timer-t
msgbox fn,,"Найдено файлов " & (ind+1)
end sub
Владимир.