Что нового

Поиск файла по маске на CD-ROM

bomond

Новичок
Сообщения
8
Репутация
0
Здравствуйте уважаемые форумчане! Решил потихоньку осваивать autoIt и для более эффективного процесса выбрал небольшую практическую задачу. Суть такова, необходимо получить путь к файлу с определенным расширением. Файл расположен на компакт диске. Я так понимаю надо произвести поиск всех CD-ROM в системе, потом организовать поиск файла по маске на найденных CD-ROM приводах. А вот как это сделать пока не въеду. Помогите пожалуйста кто чем может :smile: По форуму искал, но ничего не нашел.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Вам нужно почитать о функциях:
Код:
DriveGetDrive
FileFindFirstFile
FileFindNextFile
For
While
Exitloop
FileClose
 
Автор
bomond

bomond

Новичок
Сообщения
8
Репутация
0
Да, про эти функции я прочитал в справке, попробовал позапускать примеры, все работает, но пока картина у меня не выстраивается. CD-ROM в системе может быть сколько угодно, соответственно нужно наверное определить те из них, которые доступны, и на них искать файл. По условию файл всегда расположен по такому пути (пример E:\folder\xxx.txt). Но имя папки в которой лежит файл всегда разное от диска к диску. Функция FileFindFirstFile ищет файл в текущей директории, так что даже если я определю буквы доступных дисков, поиск по ним ничего не даст. Вот это мне не понятно. Так же непонятно как записать в переменную полный путь к найденному файлу. Я в программировании практически дуб.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Код:
#include <array.au3> ;Подключаем библиотеку массивов, для того что бы работала функция _ArrayDisplay
$aCD = DriveGetDrive("CDROM") ;Вернет массив букв CDROM-ов.
;Работать с массивами можно с помощью функции FOR
_ArrayDisplay($aCD) ;Посмотрим, что содержится в массиве. В готовой программе эту строчку естественно нужно убрать или закоментировать.
;В колонке ROW  - цифры - индексы массива
;Причем в строке с индексом 0  - указано количество CDROM-ов
;В колонке Col 0 - буквы дисков CDROM
;Значит нужно по очереди их обработать.
;Воспользуемся простейшим циклом

For $i = 1 To $aCD[0] ;$aCD[0] - означает получить строчку из массива $aCD с индексом 0. Там как ты помнишь количество CDROM-ов
	;Начинаем с 1 т.к в 0 индексе общее количество.
	;В этом цикле $i будет меняться от 1 до $aCD[0]
	;Например, за сменой $i можно понаблюдать вставив строчку ConsoleWrite("Текущее значение переменной $i = "& $i & @LF)

	$sDisk = $aCD[$i] ;Присваиваем переменной $sDisk $i-ый элемент массива. 1,2,3 до $aCD[0]
	ConsoleWrite("Сейчас работаем с диском: " & $sDisk & @LF) ;Посмотрим - какая выбрана буква
	;Откроем пример  по FileFindFirstFile
	;В качестве параметра FileFindFirstFile - принимаем путь для поиска, пусть поддерживает подстановочные знаки * и ?
	;Я не использую подстановочные знаки, поэтому скрипт слегка упростится.

	;Т.к по условию файл находится на дисках и имеет вид E:\folder\xxx.txt где диск E: - любой диск CDROM, то составим путь поиска.

	$sSearch = $sDisk & "\DirectX\DSETUP.dll"
	ConsoleWrite("Сформированна строка для поиска: " & $sSearch & @LF) ;Посмотрим, какой составлен путь.
	;Выполним функцию FileFindFirstFile
	Local $search = FileFindFirstFile($sSearch)

	;Дальше со справки копируем остальную часть, но немного переделаем
	If $search = -1 Then
		MsgBox(4096, "Error", "Ничего не найдено.")
;~     Exit  - нам не нужно завершать работу программы, а нужно попробывать другой диск поэтому заменим на команду ContinueLoop
		ContinueLoop ;она продолжит цикл не переходя на последующие строки.
	EndIf
	;На эту строчку программы мы попадем только в случае успешного поиска.
	;Поэтому копируем пример со справки дальше.

	While 1
		Local $file = FileFindNextFile($search)
		If @error Then ExitLoop ;
		;Файл найден, и переменная $file равна строке DSETUP.dll
		;Это значит что поиск по полному пути - прошел удачно и ответ содержится в перменной $sSearch

		ConsoleWrite("Нашелся файл: " & $sSearch & @LF) ;Выведем ее в консоль.
		ConsoleWrite("Переменная $file равна" & $file & @LF)
	WEnd

Next
FileClose($search) ;закрываем хэндл поиска.
;Но если тебе нужно просто проверить есть ли файл по указанному пути - то пользуйся функцией FileExists



Добавлено:
Сообщение автоматически объединено:

Этот скрипт нужно запускать в редакторе SciTe клавишей F5


Добавлено:
Сообщение автоматически объединено:

Если имя папки не известно, то ищи пользовательскую функцию _FileSearch на форуме, т.к в autoit аналогов нет.


Добавлено:
Сообщение автоматически объединено:

Вот она
http://azjio.ucoz.ru/publ/skripty_autoit3/funkcii/filesearch/11-1-0-33
 
Автор
bomond

bomond

Новичок
Сообщения
8
Репутация
0
Спасибо большое, буду разбираться.
 

Yuri

AutoIT Гуру
Сообщения
737
Репутация
282
bomond
Вот еще, мне так кажется, будет полезным
http://autoit-script.ru/index.php/topic,8266.0.html
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
Код:
$aArray = DriveGetDrive("cdrom")
For $1i = 1 To UBound($aArray) - 1
	$aReturn = _FileSearch($aArray[$1i], "*.txt", 1, 1)
	For $i = 1 To UBound($aReturn) - 1
		MsgBox(0, '', $aReturn[$i])
	Next
	Next


; #FUNCTION# ====================================================================================================
; Author.........:  G.Sandler (MrCreatoR).
; ===============================================================================================================
Func _FileSearch($sPath, $sFileMask = "*", $iFlag = 0, $iSubDir = 1, $iSort = 0)
	Local $sOutBin, $sOut, $aOut, $sRead, $hDir, $sAttrib, $sFiles
	If Not StringInStr(FileGetAttrib($sPath), "D") Then
		Return SetError(1, 0, 0)
	EndIf
	If $iSubDir = 1 Then
		$sAttrib &= ' /S'
	EndIf
	If $iSort = 1 Then
		$sAttrib &= ' /O:N'
	EndIf
	Switch $iFlag
		Case 1
			$sAttrib &= ' /A-D'
		Case 2
			$sAttrib &= ' /AD'
		Case Else
			$sAttrib &= ' /A'
	EndSwitch
	$sOut = StringToBinary('0' & @CRLF, 2)
	$sPath = StringRegExpReplace($sPath, '\\+$', '')
	$sFileMask = StringRegExpReplace($sFileMask, '^;+|;+$', '')
	$sFileMask = StringRegExpReplace($sFileMask, ';{2,}', ';')
	$aMasks = StringSplit($sFileMask, ';')
	For $i = 1 To $aMasks[0]
		If StringStripWS($aMasks[$i], 8) = "" Then
			ContinueLoop
		EndIf
		$sFiles &= '"' & $sPath & '\' & $aMasks[$i] & '"'
		If $i < $aMasks[0] Then
			$sFiles &= ';'
		EndIf
	Next
	$hDir = Run(@ComSpec & ' /U /C DIR ' & $sFiles & ' /B' & $sAttrib, @SystemDir, @SW_HIDE, 6)
	While 1
		$sRead = StdoutRead($hDir, False, True)
		If @error Then
			ExitLoop
		EndIf
		If $sRead <> "" Then
			$sOut &= $sRead
		EndIf
	WEnd
	$aOut = StringRegExp(BinaryToString($sOut, 2), '[^\r\n]+', 3)
	If @error Or UBound($aOut) < 2 Then
		Return SetError(2, 0, 0)
	EndIf
	$aOut[0] = UBound($aOut) - 1
	Return $aOut
EndFunc   ;==>_FileSearch
или просто через функцию
Код:
FileSelectFolder


Код:
$folder_file = FileSelectFolder('','')
	$aReturn = _FileSearch($folder_file, "*.txt", 1, 1)
	For $i = 1 To UBound($aReturn) - 1
		MsgBox(0, '', $aReturn[$i])
	Next
 
Автор
bomond

bomond

Новичок
Сообщения
8
Репутация
0
Спасибо. А может может как то помочь тот факт, что папка, в которой лежит файл всегда имеет кириллическое имя?
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
помочь чему? скрипт, который я привел, ищет файлы с расширением .txt на всех сидиромах. если есть вложенные папки, то и в них ищет.
bomond, что у тебя не срастается?
 
Автор
bomond

bomond

Новичок
Сообщения
8
Репутация
0
Не срастается то, что я не могу запустить Ваш скрипт. Вот код:
Код:
  #include <FileOperations.au3>
	$folder_file = FileSelectFolder('','')
           $aReturn = _FileSearch($folder_file, "*.txt", 1, 1)
           For $i = 1 To UBound($aReturn) - 1
           MsgBox(0, '', $aReturn[$i])
           Next
Или я не то приинклюдил. Ошибка такая:
Код:
ERROR: _FileSearch(): undefined function.
Я так понимаю мне нужно подключить скрипт _FileSearch.au3, я не пойму где его взять.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
полный скрипт под кнопочкой "подробнее" :smile:
тот что ты скопировал это лишь пример как можно изменить основной скрипт..будет так
Код:
$folder_file = FileSelectFolder('','')
    $aReturn = _FileSearch($folder_file, "*.txt", 1, 1)
    For $i = 1 To UBound($aReturn) - 1
        MsgBox(0, '', $aReturn[$i])
    Next

; #FUNCTION# ====================================================================================================
; Author.........:  G.Sandler (MrCreatoR).
; ===============================================================================================================
Func _FileSearch($sPath, $sFileMask = "*", $iFlag = 0, $iSubDir = 1, $iSort = 0)
    Local $sOutBin, $sOut, $aOut, $sRead, $hDir, $sAttrib, $sFiles
    If Not StringInStr(FileGetAttrib($sPath), "D") Then
        Return SetError(1, 0, 0)
    EndIf
    If $iSubDir = 1 Then
        $sAttrib &= ' /S'
    EndIf
    If $iSort = 1 Then
        $sAttrib &= ' /O:N'
    EndIf
    Switch $iFlag
        Case 1
            $sAttrib &= ' /A-D'
        Case 2
            $sAttrib &= ' /AD'
        Case Else
            $sAttrib &= ' /A'
    EndSwitch
    $sOut = StringToBinary('0' & @CRLF, 2)
    $sPath = StringRegExpReplace($sPath, '\\+$', '')
    $sFileMask = StringRegExpReplace($sFileMask, '^;+|;+$', '')
    $sFileMask = StringRegExpReplace($sFileMask, ';{2,}', ';')
    $aMasks = StringSplit($sFileMask, ';')
    For $i = 1 To $aMasks[0]
        If StringStripWS($aMasks[$i], 8) = "" Then
            ContinueLoop
        EndIf
        $sFiles &= '"' & $sPath & '\' & $aMasks[$i] & '"'
        If $i < $aMasks[0] Then
            $sFiles &= ';'
        EndIf
    Next
    $hDir = Run(@ComSpec & ' /U /C DIR ' & $sFiles & ' /B' & $sAttrib, @SystemDir, @SW_HIDE, 6)
    While 1
        $sRead = StdoutRead($hDir, False, True)
        If @error Then
            ExitLoop
        EndIf
        If $sRead <> "" Then
            $sOut &= $sRead
        EndIf
    WEnd
    $aOut = StringRegExp(BinaryToString($sOut, 2), '[^\r\n]+', 3)
    If @error Or UBound($aOut) < 2 Then
        Return SetError(2, 0, 0)
    EndIf
    $aOut[0] = UBound($aOut) - 1
    Return $aOut
EndFunc   ;==>_FileSearch
вот тебе второй вариант.
то есть в первом варианте мы задаем искать только на сидиромах, а в этом варианте мы выбираем папку или диск для поиска
 
Автор
bomond

bomond

Новичок
Сообщения
8
Репутация
0
Спасибо, проясняется, запустить удалось. :smile: Только мне теперь надо чтобы не окошко с перечислением найденных файлов выводилось, а просто путь к найденному файлу занести в какую-нибудь переменную. Я хочу этот путь потом вставить в поле ввода в другой программе. Я правильно понимаю, что полный путь к найденному файлу содержится в $aReturn?
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
если нужно найти один единственный файл, то можно так

Код:
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

$Form1 = GUICreate("Form1", 602, 194, 192, 124)
$Input1 = GUICtrlCreateInput("Input1", 96, 80, 441, 21)
$Button1 = GUICtrlCreateButton("Button1", 400, 136, 75, 25)
GUISetState(@SW_SHOW)


While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $Button1
			$folder_file = FileSelectFolder('', '')
			$aReturn = _FileSearch($folder_file, "специальный документ.txt", 1, 1)
			GUICtrlSetData($Input1, $aReturn[1])
	EndSwitch
WEnd
Func _FileSearch($sPath, $sFileMask = "*", $iFlag = 0, $iSubDir = 1, $iSort = 0)
	Local $sOutBin, $sOut, $aOut, $sRead, $hDir, $sAttrib, $sFiles
	If Not StringInStr(FileGetAttrib($sPath), "D") Then
		Return SetError(1, 0, 0)
	EndIf
	If $iSubDir = 1 Then
		$sAttrib &= ' /S'
	EndIf
	If $iSort = 1 Then
		$sAttrib &= ' /O:N'
	EndIf
	Switch $iFlag
		Case 1
			$sAttrib &= ' /A-D'
		Case 2
			$sAttrib &= ' /AD'
		Case Else
			$sAttrib &= ' /A'
	EndSwitch
	$sOut = StringToBinary('0' & @CRLF, 2)
	$sPath = StringRegExpReplace($sPath, '\\+$', '')
	$sFileMask = StringRegExpReplace($sFileMask, '^;+|;+$', '')
	$sFileMask = StringRegExpReplace($sFileMask, ';{2,}', ';')
	$aMasks = StringSplit($sFileMask, ';')
	For $i = 1 To $aMasks[0]
		If StringStripWS($aMasks[$i], 8) = "" Then
			ContinueLoop
		EndIf
		$sFiles &= '"' & $sPath & '\' & $aMasks[$i] & '"'
		If $i < $aMasks[0] Then
			$sFiles &= ';'
		EndIf
	Next
	$hDir = Run(@ComSpec & ' /U /C DIR ' & $sFiles & ' /B' & $sAttrib, @SystemDir, @SW_HIDE, 6)
	While 1
		$sRead = StdoutRead($hDir, False, True)
		If @error Then
			ExitLoop
		EndIf
		If $sRead <> "" Then
			$sOut &= $sRead
		EndIf
	WEnd
	$aOut = StringRegExp(BinaryToString($sOut, 2), '[^\r\n]+', 3)
	If @error Or UBound($aOut) < 2 Then
		Return SetError(2, 0, 0)
	EndIf
	$aOut[0] = UBound($aOut) - 1
	Return $aOut
EndFunc   ;==>_FileSearch
 
Автор
bomond

bomond

Новичок
Сообщения
8
Репутация
0
joiner, спасибо большое! У меня получилось, файл находится и путь к нему вставляется в форму ввода. Теперь у меня такой вопрос. После того, как программа выбрала файл, пользователю предлагается ввсести пароль от этого файла. Пароль всегда фиксированной длинны - 12 символов. Нужно сделать каким то образом проверку на количество введенных символов и как только их будет введено 12, нажать кнопку далее. Окошко вот такое
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
bomond
по правилам форума: один вопрос - одна тема. но сначала поищи по форуму . очень много вопросов обсуждалось. ;)
 
Автор
bomond

bomond

Новичок
Сообщения
8
Репутация
0
С поиском разобрался, всем спасибо. Тему наверное можно считать решенной :beer:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
bomond [?]
Тему наверное можно считать решенной

[info border=#0000ff float=left]На форуме принято помечать тему решенной после получения ответа на свой вопрос!
Вверху или внизу темы нажмите на ссылку такого вида:
package_old.gif
Тема не решена
[/info]
 
Верх