Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   AutoIt (http://forum.oszone.net/forumdisplay.php?f=103)
-   -   [решено] Рекурсивный поиск файла (http://forum.oszone.net/showthread.php?t=166317)

cra5h_ 20-01-2010 10:37 1324937

[решено] Рекурсивный поиск файла
 
Поиск файла выполняется при помощи функции, и выполняется очень долго. Возможно ли реализовать поиск файла в каталогах и подкаталогах другим способом - более быстрым?

Код:

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 1325282

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

Creat0R 21-01-2010 00:48 1325602

Код:

#include <Array.au3>

$aReturn = _FileSearch(@WindowsDir, "File\....$", 0)

_ArrayDisplay($aReturn)

Func _FileSearch($sPath, $sRegExp_FileMask, $iCaseSense=0)
    Local $iPID, $sStdOutRead, $aRet, $sFindStr, $sCaseStr

    If Not $iCaseSense Then $sCaseStr = ' /I'
    $sFindStr = 'Dir "' & $sPath & '" /S /B | FindStr' & $sCaseStr & ' /R "' & $sRegExp_FileMask & '"'

    $iPID = Run(@ComSpec & ' /C ' & $sFindStr, @SystemDir, @SW_HIDE, 2)

    While 1
        $sStdOutRead &= StdoutRead($iPID)
        If @error <> 0 Then ExitLoop
    WEnd

    $aRet = StringSplit(StringStripCR(StringStripWS($sStdOutRead, 3)), @LF)
    Return SetError(@error, 0, $aRet)
EndFunc

Цитата:

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

Врядли оно будет быстрее (в AutoIt).

cra5h_ 21-01-2010 10:28 1325819

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

Creat0R 21-01-2010 10:34 1325823

Цитата:

Цитата cra5h_
первыми двумя способами файл ищется 14-16 сек, последним способом 49-52 »

Ну так в чём проблема, первый способ значит быстрее ;).

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

cra5h_ 21-01-2010 10:37 1325825

имя файла задаю полное, файл в папках существует такой только один. виндовым поиском ищет до 10 сек

cra5h_ 21-01-2010 11:18 1325867

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

Yashied 21-01-2010 12:47 1325933

Цитата:

Цитата cra5h_
Подскажите как остановить функцию поиска файла после того как файл найден, потому как при нахождении файла функция продолжает сканировать остальные папки. »

Код:

#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 1325954

Цитата:

Цитата cra5h_
коллекция скриптов с рекурсивным поиском пополняется »

тогда до кучи, вариант через 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 1325958

работает пасиба

Sp01LeR 21-01-2010 16:13 1326132

Цитата:

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

Врядли оно будет быстрее (в AutoIt).

В WinAPI есть продвинутая функция FindFirstFileEx(работает только в win2000 и выше) - вот ссылка на мануал

asdf8 21-01-2010 17:29 1326211

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

Creat0R 21-01-2010 18:06 1326243

Цитата:

Цитата asdf8
Можно значительно ускорить поиск файлов, если избавиться от рекурсии. »

Вот так:

Код:

$sFile = _FileSearch(@DesktopDir, "test.txt")
MsgBox(64, 'Title', $sFile)

Func _FileSearch($sPath, $sMask="*")
    If Not StringInStr(FileGetAttrib($sPath & "\"), "D") Then Return SetError(1, 0, 0)

    Local $hSearch, $sFindNext, $sFilePath, $iPathIsFolder, $i = 0, $sRet = -1
    Local $sRegExpFilter = StringReplace(StringReplace(StringReplace($sMask, ".", "\."), "*", ".*"), "?", ".")
    Local $iMax_Ret_Paths = 10000
    Local $aPathesArr[$iMax_Ret_Paths+1] = [1, $sPath]

    While $i < $aPathesArr[0]
        $i += 1

        $hSearch = FileFindFirstFile($aPathesArr[$i] & "\*")
        If $hSearch = -1 Then ContinueLoop

        While 1
            $sFindNext = FileFindNextFile($hSearch)
            If @error Then ExitLoop

            $sFilePath = $aPathesArr[$i] & "\" & $sFindNext
            $iPathIsFolder
= StringInStr(FileGetAttrib($sFilePath & "\"), "D")

            If $iPathIsFolder Then
                If $aPathesArr[0] >= $iMax_Ret_Paths Then
                    $iMax_Ret_Paths *= 2
                    ReDim $aPathesArr[$iMax_Ret_Paths+1]
                EndIf

                $aPathesArr[0] += 1
                $aPathesArr[$aPathesArr[0]] = $sFilePath
            ElseIf StringRegExp($sFindNext, "(?i)\A" & $sRegExpFilter & "\z") Then
                $sRet = $sFilePath
                ExitLoop
            EndIf
        WEnd

        FileClose($hSearch)
        If $sRet <> -1 Then ExitLoop
    WEnd

    Return SetError(Number($sRet = -1), 0, $sRet)
EndFunc


asdf8 21-01-2010 18:36 1326260

Цитата:

Цитата Creat0R
Вот так: »


Код:

#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 1326335

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

asdf8 21-01-2010 20:55 1326356

Цитата:

Цитата semiono
пример по типам *.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 1326507

Цитата:

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

А так:

Код:

#include <Array.au3>

$begin1 = TimerInit()
$aReturn = _FileSearch(@WindowsDir, "*.ini")
$dif1 = TimerDiff($begin1)

_ArrayDisplay($aReturn, Round($dif1, 2))

Func _FileSearch($sPath, $sFileMask)
    Local $iPID, $sStdOutRead, $aRet

    $iPID
= Run(@ComSpec & ' /C Dir "' & $sPath & '\' & $sFileMask & '" /S /B /A RASH', @SystemDir, @SW_HIDE, 6)

    While 1
        $sStdOutRead &= StdoutRead($iPID)
        If @error <> 0 Then ExitLoop
    WEnd

    $aRet = StringSplit(StringStripCR(StringStripWS($sStdOutRead, 3)), @LF)
    Return SetError(@error, 0, $aRet)
EndFunc

?
:)

madmasles 22-01-2010 00:19 1326519

Creat0R,

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

PS

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

asdf8 22-01-2010 01:34 1326570

Цитата:

Цитата Creat0R
А так: »

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

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

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

Creat0R 22-01-2010 01:55 1326581

Цитата:

Цитата asdf8
для моей функции »

У себя не замечаю такую разницу, функция с использованием Dir отрабатывает намного быстрее чем всё остальное.

Цитата:

Цитата asdf8
Интересно - можно еще быстрее? »

Сарказм? к чему оно?

amel27 22-01-2010 12:47 1326845

Цитата:

Цитата asdf8
Интересно - можно еще быстрее? »

второй прогон можно, если результат первого сохранить в файл... :teeth:

asdf8 22-01-2010 13:58 1326902

Цитата:

Цитата Creat0R
Сарказм? »

Конечно нет.
Есть программка FindOnClick, которая ищет файлы на порядок быстрее всего того, что я вообще видел.
Думал, может кто знает, как?

madmasles 22-01-2010 14:40 1326953

Присоединяюсь к вопросу asdf8.
FindOnClick действительно очень быстро ищет файлы.

Creat0R 22-01-2010 17:56 1327139

Вам нужна скорость, покурите функций _FileListToArray* из темы на оф. форуме: Improvement of included _FileListToArray function
Там было предложено немало хороших улучшений.

Creat0R 22-01-2010 18:34 1327172

Цитата:

Цитата asdf8
Есть программка FindOnClick, которая ищет файлы на порядок быстрее всего того, что я вообще видел. »

Ну вообще то она поддерживает командную строку, думает будет не сложно использовать её в качестве "поисковика"?

timsky 22-01-2010 19:03 1327193

Windows 7 x64 Ultimate. Поиск @WindowsDir, "*.*":

Вариант asdf8 из этого поста 17590 мсек и находит 66247 файлов.

Вариант Creat0R из этого поста 3828 мсек и находит 81241 файлов.


TotalCommander 7.50a (включено отображение скрытых файлов) находит 64237 файлов и 14557 папок за 34 секунды.
ViewFD 2.4.3.0 (дефолтовые опции) находит 64240 файлов за 2 секунды.

Проводник 76757 объектов
При включенном отображении скрытых файлов - 76908
При включенном отображении скрытых и системных файлов - 77054

SearchMyFiles 1.37 от NirSoft.net - 64243 файла и 14525 папок.


ЗЫ: тестил в таком же порядке, в котором отписал.

Creat0R 22-01-2010 20:23 1327243

Цитата:

Цитата timsky
Вариант asdf8 из этого поста 17590 мсек и находит 66247 файлов.
Вариант Creat0R из этого поста 3828 мсек и находит 81241 файлов. »

Мой вариант ищет все файлы, включая скрытые, только для чтения, архивные и системные.

Цитата:

Цитата timsky
тестил в таком же порядке, в котором отписал »

Но эти тесты почти ничего не показывают, т.к поиск возвращает разное количество файлов.

timsky 23-01-2010 03:07 1327469

Цитата:

Цитата Creat0R
Но эти тесты почти ничего не показывают, т.к поиск возвращает разное количество файлов. »

Я и ничего не пытался доказать.

Просто заметил, что файловые менеджеры и SearchMyFiles возвращают примерно одинаковое кол-во файлов (м/у запусками немного различается), твой вариант выдает больше всего файлов, а вот вариант asdf8 как-то не вписывается в общую картину.
У проводника Виндовс вообще свои соображения на сей счет, только ему известные. :)

Sp01LeR 24-01-2010 22:04 1328861

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

madmasles 04-02-2010 19:12 1339077

Creat0R,
Цитата:

Цитата Creat0R
$iPID = Run(@ComSpec & ' /C ChCp 1251 & Dir "' & $sPath & '\' & $sFileMask & '" /S /B /A RASH', @SystemDir, @SW_HIDE, 6) »

У меня не работает.
На скриншоте ˜Ё«®ў - это юзер русскими буквами, ђ*Ў®зЁ© бв®« - Рабочий стол.
Почему, не понятно?

Iska 04-02-2010 19:51 1339112

К сожалению, такой способ не сработает, поскольку несмотря на то, что chcp выполнится, и кодовая страница сменится…
читать дальше »
Дело в том, что узнает об этом изменении только команда в следующей строке, а не в текущей: vbscript: запуск консольного приложения с чтением его вывода, см. примечание в конце. Сие можно также проверить, перенаправив вывод в текстовый файл в том и другом примере.

Creat0R 04-02-2010 19:55 1339114

Цитата:

Цитата Iska
узнает об этом изменении только команда в следующей строке, а не в текущей »

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

madmasles 04-02-2010 20:09 1339126

Iska,
Creat0R,
Значит я был прав насчет Encoding_UDF. А то я расстроился, думал опять руки кривые.

Iska 04-02-2010 21:15 1339188

Цитата:

Цитата Creat0R
Оказывается что в таком образе даже следующая строка не принимает кодовую страницу, я пробовал создавать временный бат-файл с двумя строками, что при выводе в поток, что при выводе в файл, код. страница не меняется

Хмм… Речь только про пакетные файлы? Или в трактовке чтения вывода в AutoIt? А то я что-то запутался. Для пакетных файлов у меня такое работает:

читать дальше »
0001.cmd
Код:

chcp 1251>nul
pushd "%ProgramFiles%" && dir

0002.cmd
Код:

chcp 1251>nul && pushd "%ProgramFiles%" && dir
И тот и другой пакетный файл запускаю в отдельном интерпретаторе команд «cmd.exe» (с умолчальной кодовой страницей 866), как:
Код:

0001.cmd > 0001.txt
и
Код:

0002.cmd > 0002.txt
соответственно. В результате получаю два текстовых файла (привожу частичные копии с экрана редактора Far Manager, кодировка указана в верхней строке):
Код:

C:\03\0001.txt                                          Win-1251  Строка

C:\03>chcp 1251 1>nul

C:\03>pushd "C:\Program Files"  && dir
 Том в устройстве C не имеет метки.
 Серийный номер тома: 246E-586A

 Содержимое папки C:\Program Files

04.02.2010  16:33    <DIR>          .
04.02.2010  16:33    <DIR>          ..
19.01.2009  10:09    <DIR>          7-Zip
01.08.2008  20:00    <DIR>          Account Lockout and Management Tools

Код:

C:\03\0002.txt                                                DOS  Строка

C:\03>chcp 1251  1>nul  && pushd "C:\Program Files"  && dir
 Том в устройстве C не имеет метки.
 Серийный номер тома: 246E-586A

 Содержимое папки C:\Program Files

04.02.2010  16:33    <DIR>          .
04.02.2010  16:33    <DIR>          ..
18.06.2009  11:37    <DIR>          01
19.01.2009  10:09    <DIR>          7-Zip
01.08.2008  20:00    <DIR>          Account Lockout and Management Tools

Первый («0001.txt») в кодировке OEM, второй («0002.txt») — в кодировке ANSI.

Creat0R, если не сложно, приведите Ваш код, как Вы пробовали.

Creat0R 04-02-2010 23:55 1339307

Цитата:

Цитата Iska
приведите Ваш код, как Вы пробовали »

Примерно так:

Код:

$sBat = _
    '@echo off' & @CRLF & _
    'chcp 1251 > nul' & @CRLF & _
    'dir /b "' & @DesktopDir & '\*.txt"'

$hFile = FileOpen("test_dir.bat", 2)
FileWrite($hFile, $sBat)
FileClose($hFile)

$sSdOutRead = ""
$iPid = Run(@DesktopDir & '\test_dir.bat', @DesktopDir, @SW_HIDE, 2)

While 1
    $sSdOutRead &= StdoutRead($iPid)
    If @error <> 0 Then ExitLoop
WEnd

ConsoleWrite($sSdOutRead & @CRLF)

Но я ошибся немного, при тестах с выводом в файл я забыл убрать флаг указывающий на вывод в поток :) - Так работает:

Код:

#include <Array.au3>

$aReturn = _FileSearch(@DesktopDir, "*.txt")
_ArrayDisplay($aReturn)

Func _FileSearch($sPath, $sFileMask)
    Local $sBatContent, $sBatFile, $sTmpFile, $hFile, $sRet, $aRet

    $sBatFile
= @TempDir & "\~FileSearch.bat"
    $sTmpFile = @TempDir & "\~FileSearch.tmp"

    $sBatContent = _
        '@ECHO OFF' & @CRLF & _
        'CHCP 1251 > Nul' & @CRLF & _
        'Dir "' & $sPath & '\' & $sFileMask & '" /S /B /A RASH>"%Temp%\~FileSearch.tmp'

    $hFile = FileOpen($sBatFile, 2)
    FileWrite($hFile, $sBatContent)
    FileClose($hFile)

    RunWait($sBatFile, @TempDir, @SW_HIDE)
    $sRet = FileRead($sTmpFile)

    FileDelete($sBatFile)
    FileDelete($sTmpFile)

    $aRet = StringSplit(StringStripCR(StringStripWS($sRet, 3)), @LF)
    Return SetError(@error, 0, $aRet)
EndFunc


80971815772 05-02-2010 03:14 1339382

расширеный поиск (?)
 
есть - ф-ция у Креатора,мне она очень понравилась.Но в чем проблема...


Код:

Func _FileSearch($sPath, $sMask="*")
    If Not StringInStr(FileGetAttrib($sPath & "\"), "D") Then Return SetError(1, 0, 0)

    Local $hSearch, $sFindNext, $sFilePath, $iPathIsFolder, $i = 0, $sRet = -1
    Local $sRegExpFilter = StringReplace(StringReplace(StringReplace($sMask, ".", "\."), "*", ".*"), "?", ".")
    Local $iMax_Ret_Paths = 10000
    Local $aPathesArr[$iMax_Ret_Paths+1] = [1, $sPath]

    While $i < $aPathesArr[0]
        $i += 1

        $hSearch = FileFindFirstFile($aPathesArr[$i] & "\*")
        If $hSearch = -1 Then ContinueLoop

        While 1
            $sFindNext = FileFindNextFile($hSearch)
            If @error Then ExitLoop

            $sFilePath = $aPathesArr[$i] & "\" & $sFindNext
            $iPathIsFolder = StringInStr(FileGetAttrib($sFilePath & "\"), "D")

            If $iPathIsFolder Then
                If $aPathesArr[0] >= $iMax_Ret_Paths Then
                    $iMax_Ret_Paths *= 2
                    ReDim $aPathesArr[$iMax_Ret_Paths+1]
                EndIf

                $aPathesArr[0] += 1
                $aPathesArr[$aPathesArr[0]] = $sFilePath
            ElseIf StringRegExp($sFindNext, "(?i)\A" & $sRegExpFilter & "\z") Then
                $sRet = $sFilePath
                ExitLoop
            EndIf
        WEnd

        FileClose($hSearch)
        If $sRet <> -1 Then ExitLoop
    WEnd

    Return SetError(Number($sRet = -1), 0, $sRet)
EndFunc

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


потому что пока вот что получилось... :


Код:

          FileCopy(_FileSearch("c:\","test.ini"),"c:\temp.ini")
        $OF = ("c:\temp.ini")
        _ZipAdd ("c:\temp.zip",$OF)
        FileDelete ($OF)


но это не очень удачливо просто .
может ктото , чтото посоветует..)


,kkkkkkkk

Creat0R 05-02-2010 12:09 1339615

80971815772, в оригинале эта функция таки возвращала полный список:

Код:

#include <Array.au3>

$aFiles = _FileSearch(@DesktopDir, "*.txt")

_ArrayDisplay($aFiles)

Func _FileSearch($sPath, $sMask="*")
    If Not StringInStr(FileGetAttrib($sPath & "\"), "D") Then Return SetError(1, 0, 0)

    Local $hSearch, $sFindNext, $sFilePath, $iPathIsFolder, $i = 0, $sRet = ""
    Local $sRegExpFilter = StringReplace(StringReplace(StringReplace($sMask, ".", "\."), "*", ".*"), "?", ".")
    Local $iMax_Ret_Paths = 10000
    Local $aPathesArr[$iMax_Ret_Paths+1] = [1, $sPath]

    While $i < $aPathesArr[0]
        $i += 1

        $hSearch = FileFindFirstFile($aPathesArr[$i] & "\*")
        If $hSearch = -1 Then ContinueLoop

        While 1
            $sFindNext = FileFindNextFile($hSearch)
            If @error Then ExitLoop

            $sFilePath = $aPathesArr[$i] & "\" & $sFindNext
            $iPathIsFolder
= StringInStr(FileGetAttrib($sFilePath & "\"), "D")

            If $iPathIsFolder Then
                If $aPathesArr[0] >= $iMax_Ret_Paths Then
                    $iMax_Ret_Paths *= 2
                    ReDim $aPathesArr[$iMax_Ret_Paths+1]
                EndIf

                $aPathesArr[0] += 1
                $aPathesArr[$aPathesArr[0]] = $sFilePath
            ElseIf StringRegExp($sFindNext, "(?i)\A" & $sRegExpFilter & "\z") Then
                $sRet &= $sFilePath & @CRLF
            EndIf
        WEnd

        FileClose($hSearch)
    WEnd

    $sRet = StringSplit(StringStripWS($sRet, 3), @CRLF, 1)
    If @error Then Return SetError(1, 0, -1)

    Return $sRet
EndFunc


amel27 05-02-2010 12:14 1339621

Цитата:

Цитата Creat0R
забыл убрать флаг указывающий на вывод в поток »

может всё-таки через поток?..
Код:

#include <Array.au3>

$aReturn = _FileSearch(@DesktopDir, "*.txt")
_ArrayDisplay($aReturn)

Func _FileSearch($sPath, $sFileMask)
    Local $sOut = StringToBinary("0"& @CRLF, 2), $aOut
    Local $hDir = Run(@ComSpec & ' /U/C DIR "'& $sPath &'\'& $sFileMask &'" /S/B/A-D', @SystemDir, @SW_HIDE, 6)

    While 1
        $sOut &= StdoutRead($hDir, False, True)
        If @error Then ExitLoop
    Wend


    $aOut = StringRegExp(BinaryToString($sOut,2), "[^\r\n]+", 3)
    If @error Then Return SetError(1)

    $aOut[0] = UBound($aOut)-1
    Return $aOut
EndFunc


Creat0R 05-02-2010 12:24 1339632

Цитата:

Цитата amel27
может всё-таки через поток? »

Супер! про ключ /U я и забыл совсем. А вот что делает «StringToBinary("0"& @CRLF, 2)» в начале?

Цитата:

Цитата Creat0R
что делает «StringToBinary("0"& @CRLF, 2)» в начале? »

Кажется понял, это для добавления счётчика в нулевой элемент - хитро :)

madmasles 05-02-2010 12:36 1339642

amel27,
Creat0R,
Объясните, пожалуйста, про ключ /U . В справках ничего про него не нашел.

Creat0R 05-02-2010 12:50 1339654

Цитата:

Цитата madmasles
Объясните, пожалуйста, про ключ /U . В справках ничего про него не нашел »

Набери в «Выполнить» (Win+R):

Код:

cmd.exe /?

Sp01LeR 05-02-2010 14:49 1339760

вобще-то в консоли можно задать почти любую кодировку:

Код:

"cmd.exe chcp 65001" (utf-8)
"cmd.exe chcp 65000" (utf-7)
"cmd.exe chcp 28595" (ISO-8859-5 - кирилица)
"cmd.exe chcp 20866" (KOIR-8 - русская)


Creat0R 05-02-2010 15:20 1339792

Цитата:

Цитата Sp01LeR
в консоли можно задать почти любую кодировку »

Почитай предыдущую страницу ;)

Sp01LeR 05-02-2010 17:12 1339902

Цитата:

Цитата Creat0R
Почитай предыдущую страницу »

читал, но подумал, что такая проблема только у батника - теперь понял, что в STDOUT буфер всеравно идет в OEM-кодировке...

amel27 05-02-2010 18:39 1339952

Цитата:

Цитата Sp01LeR
в STDOUT буфер всеравно идет в OEM-кодировке »

разве только сменить кодировку по умолчанию... ;)
Разное - [решено] Сбилась кодировка командной строки

Sp01LeR 05-02-2010 21:01 1340045

amel27, у меня этих проблем с ветками в реестре не было - chсp выдавало кодовую страницу 866...

изменив значение параметра "CodePage" на "4e3" (кодовая страница 1251) AutoIT берет с буфера STDOUT вместо OEM - ANSI!!! :yes:
Потом проверял с поменяв значение на "fde9":
и на MsgBox() и на записи в файл в кодировке ANSI - выводит знакомые ютээфовские крякозяблы типа

Код:

Содержимое
PS: и еще, в том топике утверждали, что после создания параметра "CodePage" нужно ребутнуть винду - но у меня все работает и без перезагрузки...

amel27 06-02-2010 05:08 1340302

Цитата:

Цитата Sp01LeR
изменив значение параметра "CodePage" на "4e3" (кодовая страница 1251) AutoIT берет с буфера STDOUT вместо OEM - ANSI!!! »

главное, не забыть вернуть обратно... а то будет как в указанном топике... :)

Цитата:

Цитата Sp01LeR
в том топике утверждали, что после создания параметра "CodePage" нужно ребутнуть винду - но у меня все работает и без перезагрузки »

для наших задач перезагрузки не треба... :)

Iska 06-02-2010 11:38 1340409

У меня работало так (относительно требования перезагрузки):
читать дальше »
1) после установки значения параметра:
Код:

[HKEY_CURRENT_USER\Console]
"Codepage"=dword:000004e3

и запуска cmd.exe, «chcp» выдавало положенное «Текущая кодовая страница: 1251»;
2) после удаления параметра «HKEY_CURRENT_USER\Console\Codepage» и запуска cmd.exe, «chcp» выдавало всё то же «Текущая кодовая страница: 1251»;
3) после установки значения параметра:
Код:

[HKEY_CURRENT_USER\Console]
"Codepage"=dword:00000362

и запуска cmd.exe, «chcp» выдавало положенное «Текущая кодовая страница: 866»;
4) после удаления параметра «HKEY_CURRENT_USER\Console\Codepage» и запуска cmd.exe, «chcp» продолжало выдавать «Текущая кодовая страница: 866».

То бишь, перезагрузка (а, правильнее, — завершение сеанса) требуется для того, чтобы вернуть умолчальную кодовую страницу 866 в том случае, когда в «HKEY_CURRENT_USER\Console» (ну, или в соответствующей файлу приложения ветви реестра, например, «%SystemRoot%_system32_cmd.exe») после удаления отсутствует параметр «Codepage».

Похоже на то, что в случае удаления параметра «Codepage» берётся последнее прочитанное оттуда и запомненное значение (2-й и 4-й рассмотренные выше этапы). Так что, вместо завершения сеанса достаточно после экспериментов добавить соответствующий кодовой странице «866» параметр «Codepage», запустить «cmd.exe» (чтобы «запомнилось» текущее значение кодовой страницы — без этого у меня не срабатывало; где и как «запомнилось» ;) — не спрашивайте, сам не знаю), выйти из этого «cmd.exe». После этого можно смело удалять параметр «Codepage» из реестра — последующие запуски «cmd.exe» будут происходить с этим самым «запомненным» значением кодовой страницы, в рассмотренной методике — «866». Ну, а после рано или поздно произведённой перезагрузки, при отсутствии в реестре параметр «Codepage», само собой, должна восстановиться кодовая страница по умолчанию.

Вот как сие выглядит у меня.


Время: 01:27.

Время: 01:27.
© OSzone.net 2001-