Как перебрать все подкаталоги

  • Автор темы PavelT100
  • Дата начала
P

PavelT100

#1
Код:
	Dim fileNameArray As String
fileNameArray = Dir$("C:\TEMP\", 0)
Do While fileNameArray <> ""
Print fileNameArray
fileNameArray = Dir$()
Loop	
Exit Function
Вот так перебираются файлы в каталоге C:\TEMP. Но:

Код:
	Dim fileNameArray As String
fileNameArray = Dir$("C:\TEMP\", 16)
Do While fileNameArray <> ""
Print fileNameArray
fileNameArray = Dir$()
Loop	
Exit Function
к моему удивлению перебираются таким образом не только подкаталоги, но и файлы. А как мне выделить только подкаталоги ?
 

morpheus

скриптописец
07.08.2006
3 915
1
#2
PavelT100
втарой параметр в Dir

Dir[$] [ ( fileSpec [ , attributeMask ] ) ]

Mask File attribute Constant
0 Normal file ATTR_NORMAL
2 Hidden file ATTR_HIDDEN
4 System file ATTR_SYSTEM
8 Volume label ATTR_VOLUME. If any other attribute is specified, ATTR_VOLUME is ignored.
16 Directory ATTR_DIRECTORY
 

Medevic

Что это ? :)
Lotus team
10.12.2004
3 346
1
#4
Хелп говорит:
Dir$ always returns the names of normal files. To include other files in the returned list of file names, specify the sum of those values in the following table that correspond to the desired kinds of files:
Т.е. этот параметр указывает что еще добавить к списку файлов. В твоём случае к списку файлов добавляется список папок.
Решение очевидно. Получить пересечение 2х списков(с папками и без).
 
P

PavelT100

#5
Решение очевидно. Получить пересечение 2х списков(с папками и без).
Эх, в моем случае я даже могу просто удалять файлы, а потом заняться обработкой подкаталогов, но я думал можно как то проще это сделать, без поиска пересечений.
 

Кирилл Шваб

Well-known member
30.06.2006
145
4
#6
Если работаешь под Windows, то можешь использовать FileSystemObject.

Пример с рекурсией (перебирающий все поддиректории в заданной):

Код:
Sub Initialize

Dim objFSO As Variant
Dim objRootFolder As Variant
Dim rootFolder As String

rootFolder = "C:\Test"

Set objFSO = CreateObject( "Scripting.FileSystemObject" )
Set objRootFolder = objFSO.GetFolder( rootFolder )
Call GetDir_Recurse( objRootFolder )

End Sub

Sub GetDir_Recurse( SrcFolder )

Dim arrSubfolders As Variant
Set arrSubfolders = SrcFolder.SubFolders
Forall currentFolder In arrSubfolders
Print currentFolder.Name
Call GetDir_Recurse( currentFolder )
End Forall

End Sub
Если надо перебирать только поддиректории 1-го уровня, то убираешь рекурсию и все.


Как вариант еще можно и с помощью Dir проходить по директории и с помощью WinAPI проверять директория ли это.

Код:
Const FILE_ATTRIBUTE_DIRECTORY = 16
Declare Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (Byval lpFileName As String) As Long

Sub Initialize

Dim fileNameArray As String
Dim rootFolder As String

rootFolder = "C:\Test\"
fileNameArray = Dir$( rootFolder, 16 )

Do While fileNameArray <> ""
If IsDir( rootFolder & fileNameArray ) Then Print fileNameArray
fileNameArray = Dir$()
Loop
End Sub

Function IsDir( srcFolder )

IsDir = False
If GetFileAttributes( srcFolder ) = FILE_ATTRIBUTE_DIRECTORY Then IsDir = True

End Function
Только когда проходишь по директориям не забывай пропускать "." и "..".
 

morpheus

скриптописец
07.08.2006
3 915
1
#7
Вот именно так я и сделал, и поставил вторым параметром 16, а мне вернули и каталоги и файлы.
ну правильно,...

Medevic правильно сослался на хэлп, так и есть. атрибут ДОБАВЛЯЕТ к нормальным файлам и другие элементы

НО! ведб можно определить атрибуты самого файла
GetFileAttr
Пример их хэлпа
This example creates a file, calls SetFileAttr to set its attributes to Read-Only, System, and Hidden, and then calls GetFileAttr to determine the file attributes.
Код:
%Include "lsconst.lss"
Dim fileNum As Integer, attr As Integer
Dim fileName As String, msg As String
fileNum% = FreeFile()
fileName$ = "data.txt"
Open fileName$ For Output As fileNum%
Close fileNum%
SetFileAttr fileName$, ATTR_READONLY + ATTR_SYSTEM + _ ATTR_HIDDEN
attr% = GetFileAttr(fileName$)
If (attr% And ATTR_READONLY) Then
msg$ = msg$ & " Read-Only "
Else
msg$ = msg$ & " Normal "
End If
If (attr% And ATTR_HIDDEN)	Then msg$ = msg$ & " Hidden "
If (attr% And ATTR_SYSTEM)	Then msg$ = msg$ & " System "
If (attr% And ATTR_DIRECTORY) Then msg$ = msg$ & " Directory "
Print msg$
SetFileAttr fileName$, ATTR_NORMAL ' Reset to normal.
Kill fileName$
 

Кирилл Шваб

Well-known member
30.06.2006
145
4
#8
Эх, знал бы про GetFileAttr раньше, не заморачивался бы с WinAPI. А то как-то раз столько времени на это дело потратил... ;-)
 

Eugen

Well-known member
22.03.2012
177
0
#9
Добрый вечер.

Подскажите пожалуйста, столкнулся со следующей дилеммой:
Есть сетевая шара с файлами. Перебираю их через CreateObject({Scripting.FileSystemObject}). Нужно отсеять системные файлы...
GetFileAttr, FileSystemObject.Attributes, да и GetFileAttributes(как в примере с kernel32) возвращают сумму констант, отвечающих за разные атрибуты. Т.е. в моем случае, у системного файла помимо признака System(4) стоит еще атрибут Archive(32). Как итог, запрашивая атрибуты всеми способами получаю цифру 36. Печаль в том, что все файлы в этой директории имеют архивный атрибут. Как в таком случае однозначно идентифицировать системный файл?
 

lmike

нет, пердело совершенство
Премиум
27.08.2008
6 567
263
#10
Как в таком случае однозначно идентифицировать системный файл
что есть системный файл? Это понятие устарело этак лет 15-20 назад
[doublepost=1487090719,1487090629][/doublepost]прочекать файлы на предмет их "нормальности" можно так
Для просмотра контента необходимо: Войти или зарегистрироваться

Для просмотра контента необходимо: Войти или зарегистрироваться
 
Симпатии: Понравилось Eugen

Мыш

Премиум
12.02.2008
1 092
10
#11
Добрый вечер.

Подскажите пожалуйста, столкнулся со следующей дилеммой:
Есть сетевая шара с файлами. Перебираю их через CreateObject({Scripting.FileSystemObject}). Нужно отсеять системные файлы...
GetFileAttr, FileSystemObject.Attributes, да и GetFileAttributes(как в примере с kernel32) возвращают сумму констант, отвечающих за разные атрибуты. Т.е. в моем случае, у системного файла помимо признака System(4) стоит еще атрибут Archive(32). Как итог, запрашивая атрибуты всеми способами получаю цифру 36. Печаль в том, что все файлы в этой директории имеют архивный атрибут. Как в таком случае однозначно идентифицировать системный файл?
Битовый AND, не?
If (attrib AND 4) = 4 Then....
 
Симпатии: Понравилось Eugen

Eugen

Well-known member
22.03.2012
177
0
#14
Фильтровать имена? Хмм... то есть просто отсеивать этот thumbs.db? А если еще какой "огрызок" появится? Это же вроде винда его создает для хранения эскизов мультимедиа. Сейчас у меня там только pdf, потом могут быть еще txt, csv, а может и просто изображения появятся...
 

lmike

нет, пердело совершенство
Премиум
27.08.2008
6 567
263
#15
Фильтровать имена? Хмм... то есть просто отсеивать этот thumbs.db? А если еще какой "огрызок" появится? Это же вроде винда его создает для хранения эскизов мультимедиа. Сейчас у меня там только pdf, потом могут быть еще txt, csv, а может и просто изображения появятся...
дык и фильтровать - чтонадо
 

lmike

нет, пердело совершенство
Премиум
27.08.2008
6 567
263
#17
добавлении нового типа файлов
уже эта фраза содержит ответ ;)
т.е. этот "раз" произойдет и сделать процедуру "расширения" скрипта не составит труда
файл приложили (с нек. типом) на сохранение - добавим фильтр
какие сложности?
 

Eugen

Well-known member
22.03.2012
177
0
#18
Мне больше нравится идея отсеять ненужное) Пользователи туда ничего не выкладывают - все файлы выгружаются системой, т.е. туда уже ничего лишнего не попадет, кроме системных файлов.

В любом случае, спасибо за помощь.