PDA

Показать полную графическую версию : [решено] Рекурсивный поиск файла


Страниц : [1] 2 3

cra5h_
20-01-2010, 10:37
Поиск файла выполняется при помощи функции, и выполняется очень долго. Возможно ли реализовать поиск файла в каталогах и подкаталогах другим способом - более быстрым?

Func _FindFiles($sRoot, $sFile)
Local $FileList
$FileList = _FileListToArray($sRoot, $sFile, 1)
If Not @error Then
For $i = 1 To $FileList[0]
$filename2 = StringMid($Filelist[$i],StringInStr($Filelist[$i],"\",0,-1)+ 1)
MsgBox(64,"",$filename2)
Next
EndIf
$FileList = _FileListToArray($sRoot, '*', 2)
If Not @error Then
For $i = 1 To $FileList[0]
_FindFiles($sRoot & '\' & $FileList[$i], $sFile)
Next
EndIf
EndFunf
попробовал такой поиск но по скорости поиска почти одинаковы

Func FileSearch($sPath, $sFileSrh) ;путь к каталогу и имя файла
Local $sFile, $Search, $sRes = ""
While 1
$Search = FileFindFirstFile($sPath & "\" & $sFileSrh)
If @error Then Return ""
While 1
$sFile = FileFindNextFile($Search)
If @error Then ExitLoop
$sFile = $sPath & "\" & $sFile
If StringInStr(FileGetAttrib($sFile), "D") > 0 Then ContinueLoop
$sRes = $sFile
MsgBox(64,"",$sRes)

WEnd
FileClose($Search)
$Search = FileFindFirstFile($sPath & "\*.*")
If @error Then ExitLoop
While 1
$sFile = FileFindNextFile($Search)
If @error Then ExitLoop
$sFile = $sPath & "\" & $sFile
If StringInStr(FileGetAttrib($sFile), "D") = 0 Then ContinueLoop
$sRes = FileSearch($sFile, $sFileSrh)
If $sRes <> "" Then ExitLoop 2
WEnd
ExitLoop
WEnd
FileClose($Search)
Return $sRes
EndFunc
файлов около 5000 и больше в 50 папках

Можно ли организовать поиск файла через WinAPI?

semiono
20-01-2010, 17:51
Мне понадобилось запустить все регфайлы в @ScriptDir & "\*\*\*....... рекурсивноооо
Как всегда ничего приличного не нашёл и был очень зол :)
Заодно поглядел что есть из файнд файл и примеров гугл, и там тоже громадные скрипты для такой простой задачи. :\
Хотя понмиаю, это у меня прстая задача, конечно там видимо что-то более серьёзное...
??

Creat0R
21-01-2010, 00:48
#include <Array.au3>

$aReturn = _FileSearch(@WindowsDir (http://www.autoitscript.com/autoit3/docs/macros.htm#@WindowsDir), "File\....$", 0)

_ArrayDisplay($aReturn)

Func (http://www.autoitscript.com/autoit3/docs/keywords.htm#Func) _FileSearch($sPath, $sRegExp_FileMask, $iCaseSense=0)
Local (http://www.autoitscript.com/autoit3/docs/keywords.htm#Local) $iPID, $sStdOutRead, $aRet, $sFindStr, $sCaseStr

If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) Not (http://www.autoitscript.com/autoit3/docs/keywords.htm#Not) $iCaseSense Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then) $sCaseStr = ' /I'
$sFindStr = 'Dir "' & $sPath & '" /S /B | FindStr' & $sCaseStr & ' /R "' & $sRegExp_FileMask & '"'

$iPID = Run (http://www.autoitscript.com/autoit3/docs/functions/Run.htm)(@ComSpec (http://www.autoitscript.com/autoit3/docs/macros.htm#@ComSpec) & ' /C ' & $sFindStr, @SystemDir (http://www.autoitscript.com/autoit3/docs/macros.htm#@SystemDir), @SW_HIDE (http://www.autoitscript.com/autoit3/docs/macros.htm#@SW_HIDE), 2)

While (http://www.autoitscript.com/autoit3/docs/keywords.htm#While) 1
$sStdOutRead &= StdoutRead (http://www.autoitscript.com/autoit3/docs/functions/StdoutRead.htm)($iPID)
If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) @error (http://www.autoitscript.com/autoit3/docs/macros.htm#@error) <> 0 Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then) ExitLoop (http://www.autoitscript.com/autoit3/docs/keywords.htm#ExitLoop)
WEnd (http://www.autoitscript.com/autoit3/docs/keywords.htm#WEnd)

$aRet = StringSplit (http://www.autoitscript.com/autoit3/docs/functions/StringSplit.htm)(StringStripCR (http://www.autoitscript.com/autoit3/docs/functions/StringStripCR.htm)(StringStripWS (http://www.autoitscript.com/autoit3/docs/functions/StringStripWS.htm)($sStdOutRead, 3)), @LF (http://www.autoitscript.com/autoit3/docs/macros.htm#@LF))
Return (http://www.autoitscript.com/autoit3/docs/keywords.htm#Return) SetError (http://www.autoitscript.com/autoit3/docs/functions/SetError.htm)(@error (http://www.autoitscript.com/autoit3/docs/macros.htm#@error), 0, $aRet)
EndFunc (http://www.autoitscript.com/autoit3/docs/keywords.htm#EndFunc)

Можно ли организовать поиск файла через WinAPI »
Врядли оно будет быстрее (в AutoIt).

cra5h_
21-01-2010, 10:28
Такс, коллекция скриптов с рекурсивным поиском пополняется. первыми двумя способами файл ищется 14-16 сек, последним способом 49-52 о_О

Creat0R
21-01-2010, 10:34
первыми двумя способами файл ищется 14-16 сек, последним способом 49-52 »
Ну так в чём проблема, первый способ значит быстрее ;).

P.S
А имя файла точное, или нужен поиск по маске? Возможно замедление из за поиска используя регулярные выражения.

cra5h_
21-01-2010, 10:37
имя файла задаю полное, файл в папках существует такой только один. виндовым поиском ищет до 10 сек

cra5h_
21-01-2010, 11:18
забросил поиск решения об быстром поиске файла. Подскажите как остановить функцию поиска файла после того как файл найден, потому как при нахождении файла функция продолжает сканировать остальные папки.

Yashied
21-01-2010, 12:47
Подскажите как остановить функцию поиска файла после того как файл найден, потому как при нахождении файла функция продолжает сканировать остальные папки. »

#Include <File.au3>

Func _FindFiles($sRoot, $sFile)
Local $FileList
$FileList = _FileListToArray($sRoot, $sFile, 1)
If Not @error Then
For $i = 1 To $FileList[0]
$filename2 = StringMid($FileList[$i], StringInStr($FileList[$i], "\", 0, -1) + 1)
MsgBox(64, "", $filename2)
Return 1
Next
EndIf
$FileList = _FileListToArray($sRoot, '*', 2)
If Not @error Then
For $i = 1 To $FileList[0]
If _FindFiles($sRoot & '\' & $FileList[$i], $sFile) Then
Return 1
EndIf
Next
EndIf
Return 0
EndFunc ;==>_FindFiles

_FindFiles('C:\', '*.au3')

amel27
21-01-2010, 13:15
коллекция скриптов с рекурсивным поиском пополняется »
тогда до кучи, вариант через WMI: :)

#include <array.au3>

$a = _FileFindLike("spuninst.exe", "C:\\WINDOWS\\$")
_ArrayDisplay($a)

Func _FileFindLike($strRight, $strLeft = @HomeDrive, $sComputer = ".")
Local $arrRight= StringRegExp($strRight, "^(.*?(?:\.([^.\\]*))?)$", 3)
If Not(IsArray($arrRight)) Then Return SetError(1, 1)

Local $arrLeft = StringRegExp($strLeft , "^([A-Za-z]:)(.*)", 3)
If Not(IsArray($arrLeft)) Then Return SetError(1, 2)

Local $strDrive = $arrLeft[0], $strPath = $arrLeft[1]
Local $strName = $arrRight[0], $strExtn = ""
If UBound($arrRight)=2 Then $strExtn = $arrRight[1]

Local $objWMI = ObjGet("winmgmts:\\" & $sComputer & "\root\cimv2")
If Not(IsObj($objWMI)) Then Return SetError(2, 1, "")

Local $strQuery = 'SELECT * FROM CIM_DataFile WHERE Drive="'& $strDrive & _
'" AND Extension="'& $strExtn &'" AND Path LIKE "'& $strPath & _
'%" AND Name LIKE "%'& $strName &'"'
Local $arrRes[1] = [0], $colItems = $objWMI.ExecQuery($strQuery)
If Not(IsObj($colItems)) Then Return SetError(2, 2, "")

For $objItem In $colItems
$arrRes[0]+=1
ReDim $arrRes[$arrRes[0]+1]
$arrRes[$arrRes[0]]=$objItem.Path
Next

Return $arrRes
EndFunc

cra5h_
21-01-2010, 13:20
работает пасиба

Sp01LeR
21-01-2010, 16:13
Можно ли организовать поиск файла через WinAPI
Врядли оно будет быстрее (в AutoIt).

В WinAPI есть продвинутая функция FindFirstFileEx(работает только в win2000 и выше) - вот ссылка (http://msdn.microsoft.com/en-us/library/aa364419(VS.85).aspx) на мануал

asdf8
21-01-2010, 17:29
Можно значительно ускорить поиск файлов, если избавиться от рекурсии.
Много времени уходит на многочисленный вызов функции.

Creat0R
21-01-2010, 18:06
Можно значительно ускорить поиск файлов, если избавиться от рекурсии. »
Вот так:


$sFile = _FileSearch(@DesktopDir (http://www.autoitscript.com/autoit3/docs/macros.htm#@DesktopDir), "test.txt")
MsgBox (http://www.autoitscript.com/autoit3/docs/functions/MsgBox.htm)(64, 'Title', $sFile)

Func (http://www.autoitscript.com/autoit3/docs/keywords.htm#Func) _FileSearch($sPath, $sMask="*")
If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) Not (http://www.autoitscript.com/autoit3/docs/keywords.htm#Not) StringInStr (http://www.autoitscript.com/autoit3/docs/functions/StringInStr.htm)(FileGetAttrib (http://www.autoitscript.com/autoit3/docs/functions/FileGetAttrib.htm)($sPath & "\"), "D") Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then) Return (http://www.autoitscript.com/autoit3/docs/keywords.htm#Return) SetError (http://www.autoitscript.com/autoit3/docs/functions/SetError.htm)(1, 0, 0)

Local (http://www.autoitscript.com/autoit3/docs/keywords.htm#Local) $hSearch, $sFindNext, $sFilePath, $iPathIsFolder, $i = 0, $sRet = -1
Local (http://www.autoitscript.com/autoit3/docs/keywords.htm#Local) $sRegExpFilter = StringReplace (http://www.autoitscript.com/autoit3/docs/functions/StringReplace.htm)(StringReplace (http://www.autoitscript.com/autoit3/docs/functions/StringReplace.htm)(StringReplace (http://www.autoitscript.com/autoit3/docs/functions/StringReplace.htm)($sMask, ".", "\."), "*", ".*"), "?", ".")
Local (http://www.autoitscript.com/autoit3/docs/keywords.htm#Local) $iMax_Ret_Paths = 10000
Local (http://www.autoitscript.com/autoit3/docs/keywords.htm#Local) $aPathesArr[$iMax_Ret_Paths+1] = [1, $sPath]

While (http://www.autoitscript.com/autoit3/docs/keywords.htm#While) $i < $aPathesArr[0]
$i += 1

$hSearch = FileFindFirstFile (http://www.autoitscript.com/autoit3/docs/functions/FileFindFirstFile.htm)($aPathesArr[$i] & "\*")
If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) $hSearch = -1 Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then) ContinueLoop (http://www.autoitscript.com/autoit3/docs/keywords.htm#ContinueLoop)

While (http://www.autoitscript.com/autoit3/docs/keywords.htm#While) 1
$sFindNext = FileFindNextFile (http://www.autoitscript.com/autoit3/docs/functions/FileFindNextFile.htm)($hSearch)
If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) @error (http://www.autoitscript.com/autoit3/docs/macros.htm#@error) Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then) ExitLoop (http://www.autoitscript.com/autoit3/docs/keywords.htm#ExitLoop)

$sFilePath = $aPathesArr[$i] & "\" & $sFindNext
$iPathIsFolder = StringInStr (http://www.autoitscript.com/autoit3/docs/functions/StringInStr.htm)(FileGetAttrib (http://www.autoitscript.com/autoit3/docs/functions/FileGetAttrib.htm)($sFilePath & "\"), "D")

If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) $iPathIsFolder Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then)
If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) $aPathesArr[0] >= $iMax_Ret_Paths Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then)
$iMax_Ret_Paths *= 2
ReDim (http://www.autoitscript.com/autoit3/docs/keywords.htm#ReDim) $aPathesArr[$iMax_Ret_Paths+1]
EndIf (http://www.autoitscript.com/autoit3/docs/keywords.htm#EndIf)

$aPathesArr[0] += 1
$aPathesArr[$aPathesArr[0]] = $sFilePath
ElseIf (http://www.autoitscript.com/autoit3/docs/keywords.htm#ElseIf) StringRegExp (http://www.autoitscript.com/autoit3/docs/functions/StringRegExp.htm)($sFindNext, "(?i)\A" & $sRegExpFilter & "\z") Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then)
$sRet = $sFilePath
ExitLoop (http://www.autoitscript.com/autoit3/docs/keywords.htm#ExitLoop)
EndIf (http://www.autoitscript.com/autoit3/docs/keywords.htm#EndIf)
WEnd (http://www.autoitscript.com/autoit3/docs/keywords.htm#WEnd)

FileClose (http://www.autoitscript.com/autoit3/docs/functions/FileClose.htm)($hSearch)
If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) $sRet <> -1 Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then) ExitLoop (http://www.autoitscript.com/autoit3/docs/keywords.htm#ExitLoop)
WEnd (http://www.autoitscript.com/autoit3/docs/keywords.htm#WEnd)

Return (http://www.autoitscript.com/autoit3/docs/keywords.htm#Return) SetError (http://www.autoitscript.com/autoit3/docs/functions/SetError.htm)(Number (http://www.autoitscript.com/autoit3/docs/functions/Number.htm)($sRet = -1), 0, $sRet)
EndFunc (http://www.autoitscript.com/autoit3/docs/keywords.htm#EndFunc)

asdf8
21-01-2010, 18:36
Вот так: »



#Include <Array.au3>


$begin1 = TimerInit()
$sFile = FileList(@WindowsDir, "*.ini")
$dif1 = TimerDiff($begin1)
_ArrayDisplay($sFile,$dif1)


Func FileList($sPath, $inFilter = '*', $exFilter = '');$includeFilter='*.txt,*.htm' $excludeFilter='www,asp,desktop'
$sPath = StringRegExpReplace($sPath, '\\+$', '')
Local $aRetArray[1], $sFindNextFile, $sCurrentPath, $iFL
Global $FolderList[2]
$aRetArray[0] = 0
$FolderList[0] = 1
$FolderList[1] = $sPath
Local $sFindFirstFile = FileFindFirstFile($sPath & "\*")
If @error = 1 Then Return SetError(1, 0, -1)
#Region
If StringRight($inFilter, 1) = ',' Then $inFilter = StringTrimRight($inFilter, 1)
$inFilter = StringReplace($inFilter, '^', '\^')
$inFilter = StringReplace($inFilter, '.', '\.')
$inFilter = StringReplace($inFilter, '(', '\(')
$inFilter = StringReplace($inFilter, ')', '\)')
$inFilter = StringReplace($inFilter, '[', '\[')
$inFilter = StringReplace($inFilter, ']', '\]')
$inFilter = StringReplace($inFilter, '+', '\+')
$inFilter = StringReplace($inFilter, '$', '\$')
$inFilter = StringReplace($inFilter, '*', '.*')
$inFilter = '(?i)^' & StringReplace($inFilter, ',', '$|^') & '$'
If StringInStr($exFilter, ',') > 0 And $exFilter <> '' Then
If StringRight($exFilter, 1) = ',' Then $exFilter = StringTrimRight($exFilter, 1)
$exFilter = StringReplace($exFilter, ',', '|')
$exFilter = StringReplace($exFilter, '.', '\.')
$exFilter = StringReplace($exFilter, '(', '\(')
$exFilter = StringReplace($exFilter, ')', '\)')
$exFilter = StringReplace($exFilter, '[', '\[')
$exFilter = StringReplace($exFilter, ']', '\]')
$exFilter = StringReplace($exFilter, '+', '\+')
$exFilter = StringReplace($exFilter, '$', '\$')
$exFilter = '(?i)(' & StringReplace($exFilter, '^', '\^') & ')'
EndIf
#EndRegion
$iFL = 1
Do
$sFindFirstFile = FileFindFirstFile($FolderList[$iFL] & "\*")
If @error = 0 Then
While 1
$sFindNextFile = FileFindNextFile($sFindFirstFile)
If @error = 1 Then ExitLoop
$sCurrentPath = $FolderList[$iFL] & "\" & $sFindNextFile
If StringInStr(FileGetAttrib($sCurrentPath), "D") Then;папка
$FolderList[0] += 1
If UBound($FolderList) < $FolderList[0] + 1 Then ReDim $FolderList[$FolderList[0] + 1000]
$FolderList[$FolderList[0]] = $sCurrentPath
Else;файл
If StringRegExp($sFindNextFile, $inFilter) = 1 And ($exFilter = '' Or StringRegExp($sFindNextFile, $exFilter) = 0) Then
$aRetArray[0] += 1
If UBound($aRetArray) < $aRetArray[0] + 1 Then ReDim $aRetArray[$aRetArray[0] + 1000]
$aRetArray[$aRetArray[0]] = $sCurrentPath
EndIf
EndIf
WEnd
EndIf
FileClose($sFindFirstFile)
$iFL += 1
Until $iFL > $FolderList[0]
ReDim $aRetArray[$aRetArray[0] + 1]
ReDim $FolderList[$FolderList[0] + 1]
Return $aRetArray
EndFunc ;==>FileList


Этот скрипт осматривает папку WindowsDir в 6 раз быстрее, чем из предыдущего поста

semiono
21-01-2010, 20:17
Будте любезны зделайте мне этот пример по типам *.reg и с запуском $regfiles /s
И не ругайтесь, что я встреваю, но не понял что ищете все файлы ($includeFilter='*.txt,*.htm') чтоли? Зделайте по типам!
(GUI вывод мне не нужен...)

asdf8
21-01-2010, 20:55
пример по типам *.reg »


$path = @ScriptDir
$sFile = FileList($path, "*.reg")

If $sFile[0]>0 Then
For $i=1 To $sFile[0]
Run('regedit /s "' & $sFile[$i] & '"')
Next
EndIf


функция FileList из моего предыдущего поста.
в переменной $path указать, где искать файлы.

Creat0R
22-01-2010, 00:06
Этот скрипт осматривает папку WindowsDir в 6 раз быстрее, чем из предыдущего поста »
А так:

#include <Array.au3>

$begin1 = TimerInit (http://www.autoitscript.com/autoit3/docs/functions/TimerInit.htm)()
$aReturn = _FileSearch(@WindowsDir (http://www.autoitscript.com/autoit3/docs/macros.htm#@WindowsDir), "*.ini")
$dif1 = TimerDiff (http://www.autoitscript.com/autoit3/docs/functions/TimerDiff.htm)($begin1)

_ArrayDisplay($aReturn, Round (http://www.autoitscript.com/autoit3/docs/functions/Round.htm)($dif1, 2))

Func (http://www.autoitscript.com/autoit3/docs/keywords.htm#Func) _FileSearch($sPath, $sFileMask)
Local (http://www.autoitscript.com/autoit3/docs/keywords.htm#Local) $iPID, $sStdOutRead, $aRet

$iPID = Run (http://www.autoitscript.com/autoit3/docs/functions/Run.htm)(@ComSpec (http://www.autoitscript.com/autoit3/docs/macros.htm#@ComSpec) & ' /C Dir "' & $sPath & '\' & $sFileMask & '" /S /B /A RASH', @SystemDir (http://www.autoitscript.com/autoit3/docs/macros.htm#@SystemDir), @SW_HIDE (http://www.autoitscript.com/autoit3/docs/macros.htm#@SW_HIDE), 6)

While (http://www.autoitscript.com/autoit3/docs/keywords.htm#While) 1
$sStdOutRead &= StdoutRead (http://www.autoitscript.com/autoit3/docs/functions/StdoutRead.htm)($iPID)
If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) @error (http://www.autoitscript.com/autoit3/docs/macros.htm#@error) <> 0 Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then) ExitLoop (http://www.autoitscript.com/autoit3/docs/keywords.htm#ExitLoop)
WEnd (http://www.autoitscript.com/autoit3/docs/keywords.htm#WEnd)

$aRet = StringSplit (http://www.autoitscript.com/autoit3/docs/functions/StringSplit.htm)(StringStripCR (http://www.autoitscript.com/autoit3/docs/functions/StringStripCR.htm)(StringStripWS (http://www.autoitscript.com/autoit3/docs/functions/StringStripWS.htm)($sStdOutRead, 3)), @LF (http://www.autoitscript.com/autoit3/docs/macros.htm#@LF))
Return (http://www.autoitscript.com/autoit3/docs/keywords.htm#Return) SetError (http://www.autoitscript.com/autoit3/docs/functions/SetError.htm)(@error (http://www.autoitscript.com/autoit3/docs/macros.htm#@error), 0, $aRet)
EndFunc (http://www.autoitscript.com/autoit3/docs/keywords.htm#EndFunc)

?
:)

madmasles
22-01-2010, 00:19
Creat0R,

Вот время работы Вашей функции у меня 376.28 - Супер!!!
Результат функции от asdf8 1763.56

PS

Рано еще списывать командную строку.

asdf8
22-01-2010, 01:34
А так: »

первый прогон 4037.44
второй прогон 3680.5

для моей функции:
первый прогон 4667.5
второй прогон 1587.21

Интересно - можно еще быстрее?

Creat0R
22-01-2010, 01:55
для моей функции »
У себя не замечаю такую разницу, функция с использованием Dir отрабатывает намного быстрее чем всё остальное.

Интересно - можно еще быстрее? »
Сарказм? к чему оно?




© OSzone.net 2001-2012