Наиболее часто используемый мной скрипт, выложенный NIKZZZZ здесь. Решил изучить его для возможности манипулировать им.
Для начала вот
Этот же скрипт но с подробным описанием для изучения
А теперь модернизированный вариант этого скрипта
Добавлены режимы
$mode=0 - возвратить все файлы
$mode=1 - возвратить определённый тип файла, например log или au3 и т.д.
$mode=2 - возвратить все каталоги
$Level= от 1 до 49 по размерности массива и этого достаточно. Для файлов корневого каталога уровень вложенности равен 1, а для папок 2.
Чтобы получить содержимое каталога без подкаталогов, достаточно выполнить два цикла:
Этот скрипт работает быстрее в отличии от скриптов, отправляющих весь список файлов в массив.
Для начала вот
Код:
Global $Stack[50]
Global $Stack1[50]
$Text = ""
FileFindNextFirst("c:\windows")
While 1
$tempname = FileFindNext()
If $tempname = "" Then ExitLoop
$Text &= $tempname & @CRLF
WEnd
MsgBox(4096, '', $Text)
Func FileFindNextFirst($FindCat)
$Stack[0] = 1
$Stack1[1] = $FindCat
$Stack[$Stack[0]] = FileFindFirstFile($Stack1[$Stack[0]] & "\*.*")
Return $Stack[$Stack[0]]
EndFunc ;==>FileFindNextFirst
Func FileFindNext()
While 1
$file = FileFindNextFile($Stack[$Stack[0]])
If @error Then
FileClose($Stack[$Stack[0]])
If $Stack[0] = 1 Then
Return ""
Else
$Stack[0] -= 1
ContinueLoop
EndIf
Else
If StringInStr(FileGetAttrib($Stack1[$Stack[0]] & "\" & $file), "D") > 0 Then
$Stack[0] += 1
$Stack1[$Stack[0]] = $Stack1[$Stack[0] - 1] & "\" & $file
$Stack[$Stack[0]] = FileFindFirstFile($Stack1[$Stack[0]] & "\*.*")
ContinueLoop
Else
Return $Stack1[$Stack[0]] & "\" & $file
EndIf
EndIf
WEnd
EndFunc ;==>FileFindNext
Этот же скрипт но с подробным описанием для изучения
Код:
#include <Array.au3> ; временно для просмотра массивов
HotKeySet('{ESC}', "_Quit") ; выход по ESC
; изменил имена переменных стек1 и стек2, чтоб не запутаться в них.
Global $llllllllllll[50] ; массив будет содержать уровни вложенности, нулевой элемент будет содержать текущую вложенность
Global $sssss[50] ; массив будет содержать пути в соответствии с уровнем вложенности
$Text = ""
_FileFindNextFirst("C:\WINDOWS") ; Вызов функции с передачей в тело функции каталога
While 1
$tempname = _FileFindNext()
If $tempname = "" Then ExitLoop
$Text &= $tempname & @CRLF
WEnd
MsgBox(4096, '', $Text)
Func _FileFindNextFirst($KorenF) ; получаем каталог в переменную $KorenF. Этот вызов выполняется единожды перед циклом While-WEnd
$llllllllllll[0] = 1 ; устанавливаем элемент массива равным 1
$sssss[1] = $KorenF ; устанавливаем элемент массива равным путю к каталогу
$llllllllllll[1] = FileFindFirstFile($KorenF & "\*.*")
;$llllllllllll[$llllllllllll[0]] = FileFindFirstFile($sssss[$llllllllllll[0]] & "\*.*") ; упростили эту запись, так как в этой же функции определены значения переменных
_ArrayDisplay( $llllllllllll, "Смотрим первый llllllllllll" ) ; временно для просмотра массивов
_ArrayDisplay( $sssss, "Смотрим первый sssss" )
Return $llllllllllll[1] ; возвращаем первые элементы массива 1 и 1, что значит найдено
;так как переменные глобавльные, то $sssss[1] содержит корневой каталог поиска.
EndFunc ;==>_FileFindNextFirst
Func _FileFindNext() ; вызывается постоянно в цикле, пока не выполнится поиск всех файлов
While 1
$file = FileFindNextFile($llllllllllll[$llllllllllll[0]]) ; поиск следующего файла $llllllllllll[1]
If @error Then ; если в этом каталоге файлы закончились, то -------------------
FileClose($llllllllllll[$llllllllllll[0]]) ; закрываем закрываем поиск
If $llllllllllll[0] = 1 Then ; если находимся в корневом каталоге, то
Return "" ; выход из функции нисчем (означает что весь поиск закончен)
Else ; если находимся НЕ в корневом каталоге, то
$llllllllllll[0] -= 1 ; поднимаемся на уровень выше приближаясь к корневому каталогу
ContinueLoop ; и снова выполняем поиск
EndIf
Else ; если в этом каталоге файлы НЕ закончились, то -------------------
If StringInStr(FileGetAttrib($sssss[$llllllllllll[0]] & "\" & $file), "D") > 0 Then ; если элемент является не файлом, а каталогом, то
$llllllllllll[0] += 1 ; увеличиваем первый элемент на 1 (указывая этим уровень вложенности каталога)
$sssss[$llllllllllll[0]] = $sssss[$llllllllllll[0] - 1] & "\" & $file ; записываем во второй массив с уровнем вложенности предыдущий путь выше уровнем + имя каталога
$llllllllllll[$llllllllllll[0]] = FileFindFirstFile($sssss[$llllllllllll[0]] & "\*.*") ; выполняем поиск файла в подкаталоге и записываем в массив с соответствующем уровнем вложенности
_ArrayDisplay( $llllllllllll, "Смотрим llllllllllll" ) ; временно для просмотра массивов
_ArrayDisplay( $sssss, "Смотрим sssss" )
ContinueLoop ; снова выполняем цикл поиска файла
Else ; если элемент является файлом, а НЕ каталогом, то
Return $sssss[$llllllllllll[0]] & "\" & $file ; возвращаем из функции путь к очередному файлу
EndIf
EndIf
WEnd
EndFunc ;==>_FileFindNext
Func _Quit()
Exit
EndFunc
А теперь модернизированный вариант этого скрипта
Код:
#include <Array.au3> ; временно для просмотра массивов
HotKeySet('{ESC}', "_Quit") ; выход по ESC
; изменил имена переменных стек1 и стек2, чтоб не запутаться в них.
Global $llllllllllll[50] ; массив будет содержать уровни вложенности, нулевой элемент будет содержать текущую вложенность
Global $sssss[50] ; массив будет содержать пути в соответствии с уровнем вложенности
$Text = ""
_FileFindNextFirst("C:\WINDOWS") ; Вызов функции с передачей в тело функции каталога
While 1
$tempname = _FileFindNext('log',0,2)
If $tempname = "" Then ExitLoop
$Text &= $tempname & @CRLF
WEnd
MsgBox(4096, '', $Text)
Func _FileFindNextFirst($KorenF) ; получаем каталог в переменную $KorenF. Этот вызов выполняется единожды перед циклом While-WEnd
$llllllllllll[0] = 1 ; устанавливаем элемент массива равным 1
$sssss[1] = $KorenF ; устанавливаем элемент массива равным путю к каталогу
$llllllllllll[1] = FileFindFirstFile($KorenF & "\*.*")
;$llllllllllll[$llllllllllll[0]] = FileFindFirstFile($sssss[$llllllllllll[0]] & "\*.*") ; упростили эту запись, так как в этой же функции определены значения переменных
;_ArrayDisplay( $llllllllllll, "Смотрим первый llllllllllll" ) ; временно для просмотра массивов
;_ArrayDisplay( $sssss, "Смотрим первый sssss" )
Return $llllllllllll[1] ; возвращаем первые элементы массива 1 и 1, что значит найдено
;так как переменные глобавльные, то $sssss[1] содержит корневой каталог поиска.
EndFunc ;==>_FileFindNextFirst
;$mode=0 - возвращать файлы
;$mode=1 - возвращать типы файлы
;$mode=2 - возвращать каталоги
;$Level= от 1 до 49 по размерности массива и этого достаточно.
;$type = 'log' - позволяет задать функцию без параметров (по умолчанию поиск всех файлов).
Func _FileFindNext($type = 'log', $mode = 0, $Level=49) ; вызывается постоянно в цикле, пока не выполнится поиск всех файлов
While 1
$file = FileFindNextFile($llllllllllll[$llllllllllll[0]]) ; поиск следующего файла $llllllllllll[1]
If @error Then ; если в этом каталоге файлы закончились, то -------------------
FileClose($llllllllllll[$llllllllllll[0]]) ; закрываем закрываем поиск
If $llllllllllll[0] = 1 Then ; если находимся в корневом каталоге, то
Return "" ; выход из функции нисчем (означает что весь поиск закончен)
Else ; если находимся НЕ в корневом каталоге, то
$llllllllllll[0] -= 1 ; поднимаемся на уровень выше приближаясь к корневому каталогу
ContinueLoop ; и снова выполняем поиск
EndIf
Else ; если в этом каталоге файлы НЕ закончились, то -------------------
If StringInStr(FileGetAttrib($sssss[$llllllllllll[0]] & "\" & $file), "D") > 0 Then ; если элемент является не файлом, а каталогом, то
If $llllllllllll[0] = $Level Then ContinueLoop ; проверка уровня вложенности
$llllllllllll[0] += 1 ; увеличиваем первый элемент на 1 (указывая этим уровень вложенности каталога)
$sssss[$llllllllllll[0]] = $sssss[$llllllllllll[0] - 1] & "\" & $file ; записываем во второй массив с уровнем вложенности предыдущий путь выше уровнем + имя каталога
$llllllllllll[$llllllllllll[0]] = FileFindFirstFile($sssss[$llllllllllll[0]] & "\*.*") ; выполняем поиск файла в подкаталоге и записываем в массив с соответствующем уровнем вложенности
;_ArrayDisplay( $llllllllllll, "Смотрим llllllllllll" ) ; временно для просмотра массивов
;_ArrayDisplay( $sssss, "Смотрим sssss" )
If $mode=2 Then ; если режим поиска каталогов ($mode=2), то
Return $sssss[$llllllllllll[0]] ; возвращаем каталог
Else
ContinueLoop ; снова выполняем цикл поиска файла
EndIf
Else ; если элемент является файлом, а НЕ каталогом, то
If $mode=2 Then ContinueLoop ; если режим поиска каталогов ($mode=2), то повторяем цикл
If $mode=1 Then ; если режим поиска файлов по типу ($mode=1), то
If StringRight($sssss[$llllllllllll[0]] & "\" & $file, 4)<>'.'&$type Then ; если расширение файла НЕ соответствует
ContinueLoop ; выполняем цикл сначала
Else; если расширение файла соответствует
Return $sssss[$llllllllllll[0]] & "\" & $file ; возвращаем из функции путь к очередному файлу с соответствующи расширением
EndIf
Else ; если режим поиска не $mode=1 или $mode=2, то
Return $sssss[$llllllllllll[0]] & "\" & $file ; возвращаем из функции путь к очередному файлу с любым расширением
EndIf
EndIf
EndIf
WEnd
EndFunc ;==>_FileFindNext
Func _Quit()
Exit
EndFunc
Добавлены режимы
$mode=0 - возвратить все файлы
$mode=1 - возвратить определённый тип файла, например log или au3 и т.д.
$mode=2 - возвратить все каталоги
$Level= от 1 до 49 по размерности массива и этого достаточно. Для файлов корневого каталога уровень вложенности равен 1, а для папок 2.
Чтобы получить содержимое каталога без подкаталогов, достаточно выполнить два цикла:
Код:
_FileFindNextFirst("C:\WINDOWS") ; Вызов функции с передачей в тело функции каталога
While 1
$tempname = _FileFindNext('',2,2)
If $tempname = "" Then ExitLoop
$Text &= $tempname & @CRLF
WEnd
_FileFindNextFirst("C:\WINDOWS") ; Вызов функции с передачей в тело функции каталога
While 1
$tempname = _FileFindNext('',0,1)
If $tempname = "" Then ExitLoop
$Text &= $tempname & @CRLF
WEnd
Код:
Global $Stack[50], $Stack1[50]
$Text = ""
FileFindNextFirst("C:\WINDOWS")
While 1
$tempname = FileFindNext('',2,2)
If $tempname = "" Then ExitLoop
$Text &= $tempname & @CRLF
WEnd
FileFindNextFirst("C:\WINDOWS")
While 1
$tempname = FileFindNext('',0,1)
If $tempname = "" Then ExitLoop
$Text &= $tempname & @CRLF
WEnd
MsgBox(4096, '', $Text)
Func FileFindNextFirst($FindCat)
$Stack[0] = 1
$Stack1[1] = $FindCat
$Stack[1] = FileFindFirstFile($FindCat & "\*.*")
Return $Stack[1]
EndFunc ;==>FileFindNextFirst
;$mode=0 - файлы
;$mode=1 - типы файлов
;$mode=2 - каталоги
;$Level= от 1 до 49
Func FileFindNext($type = 'log', $mode = 0, $Level=49)
While 1
$file = FileFindNextFile($Stack[$Stack[0]])
If @error Then
FileClose($Stack[$Stack[0]])
If $Stack[0] = 1 Then
Return ""
Else
$Stack[0] -= 1
ContinueLoop
EndIf
Else
If StringInStr(FileGetAttrib($Stack1[$Stack[0]] & "\" & $file), "D") > 0 Then
If $Stack[0] = $Level Then ContinueLoop
$Stack[0] += 1
$Stack1[$Stack[0]] = $Stack1[$Stack[0] - 1] & "\" & $file
$Stack[$Stack[0]] = FileFindFirstFile($Stack1[$Stack[0]] & "\*.*")
If $mode=2 Then
Return $Stack1[$Stack[0]]
Else
ContinueLoop
EndIf
Else
If $mode=2 Then ContinueLoop
If $mode=1 Then
If StringRight($Stack1[$Stack[0]] & "\" & $file, 4)<>'.'&$type Then
ContinueLoop
Else
Return $Stack1[$Stack[0]] & "\" & $file
EndIf
Else
Return $Stack1[$Stack[0]] & "\" & $file
EndIf
EndIf
EndIf
WEnd
EndFunc ;==>FileFindNext
Этот скрипт работает быстрее в отличии от скриптов, отправляющих весь список файлов в массив.