; @AZJIO 2010.07.09 #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_OutFile=Search_duplicates.exe #AutoIt3Wrapper_icon=Search_duplicates.ico #AutoIt3Wrapper_Compression=4 #AutoIt3Wrapper_UseAnsi=y #AutoIt3Wrapper_Res_Comment=- #AutoIt3Wrapper_Res_Description=Search_duplicates.exe #AutoIt3Wrapper_Res_Fileversion=0.1.0.0 #AutoIt3Wrapper_Res_Fileversion_AutoIncrement=n #AutoIt3Wrapper_Res_LegalCopyright=AZJIO #AutoIt3Wrapper_Res_Language=1049 #AutoIt3Wrapper_Run_AU3Check=n #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Crypt.au3> #include <File.au3> #include <Array.au3> #include <GUIConstantsEx.au3> ;#include <GuiListView.au3> Global $Debug_LV = False #include <ListViewConstants.au3> #NoTrayIcon Global $Stack[50], $Stack1[50] Global $aArr, $a, $MD5Path, $Dubl HotKeySet('{ESC}', "_Quit") ; выход по ESC ;создание оболочки $Gui = GUICreate("Поиск дубликатов файлов", 500, 444, -1, -1, 0x00040000, 0x00000010) ; размер окна $CatchDrop = GUICtrlCreateInput("", 0, 0, 500, 440) GUICtrlSetState(-1, 136) GUICtrlSetResizing(-1, 1) $StatusBar = GUICtrlCreateLabel(@CRLF&'Строка состояния', 5, 380, 480, 30) GUICtrlSetResizing(-1, 512 + 256 + 64 + 2) $restart = GUICtrlCreateButton("R", 480, 2, 18, 20) GUICtrlSetTip(-1, "Перезапуск утилиты") GUICtrlSetResizing(-1, 512 + 256 + 32 + 4) $About = GUICtrlCreateButton("?", 460, 2, 18, 20) GUICtrlSetTip(-1, "О программе") GUICtrlSetResizing(-1, 512 + 256 + 32 + 4) GUICtrlCreateLabel("используйте drag-and-drop", 170, 5, 160, 18) GUICtrlSetResizing(-1, 32 + 256 + 512) GUICtrlCreateLabel("Папки", 15, 10, 60, 17) GUICtrlSetResizing(-1, 3 + 32 + 256 + 512) $folder = GUICtrlCreateList("", 10, 25, 480, 100) GUICtrlSetResizing(-1, 7 + 32 + 512) GUICtrlCreateLabel("Дубликаты", 15, 132, 60, 18) GUICtrlSetResizing(-1, 3 + 32 + 256 + 512) _Dubl() $context = GUICtrlCreateContextMenu($Dubl) $contextOpen = GUICtrlCreateMenuitem ("Открыть",$context) ; $Select = GUICtrlCreateButton("Выбор", 180, 355, 70, 25) ; GUICtrlSetResizing(-1, 512 + 256 + 64 + 4) $Clear = GUICtrlCreateButton("Очистить", 260, 355, 70, 25) GUICtrlSetResizing(-1, 512 + 256 + 64 + 4) $Search = GUICtrlCreateButton("Поиск", 340, 355, 70, 25) GUICtrlSetResizing(-1, 512 + 256 + 64 + 4) $Delete = GUICtrlCreateButton("Удалить", 420, 355, 70, 25) GUICtrlSetResizing(-1, 512 + 256 + 64 + 4) $aSizePath='' $folderList = '' $aArrOut='' GUISetState() _Crypt_Startup() While 1 $msg = GUIGetMsg() Select ; drag-and-drop - принятие каталогов Case $msg = -13 $triger = 0 If @GUI_DropId = $CatchDrop Then $aFolder = StringSplit(GUICtrlRead($CatchDrop), '|') $GuiPos = WinGetPos($Gui) GUICtrlSetPos($CatchDrop, $GuiPos[2], 0) GUICtrlSetData($CatchDrop, '') GUICtrlSetPos($CatchDrop, 0, 0) For $i = 1 To $aFolder[0] If StringInStr(FileGetAttrib($aFolder[$i]), "D") = 0 Then $triger = 1 Else GUICtrlSetData($folder, StringRegExpReplace($aFolder[$i], '(?:.*)\\(.*)$', '\1')) $folderList &= '|' & $aFolder[$i] EndIf Next EndIf If $triger = 1 Then $triger = 0 MsgBox(0, "Мелкая ошибка", 'Перетаскивайте каталоги, а не файлы.') EndIf Case $msg = $About _About() ; Очистка (обнуляем все весомые переменные) Case $msg = $Clear GUICtrlDelete ($Dubl) _Dubl() $folderList = '' GUICtrlSetData($folder, '') $aSizePath = '' $aArr = '' $aArrT = '' $TempMD5 = '' $aArrOut = '' $aArrMD5 = '' GUICtrlSetData($StatusBar,@CRLF&'Строка состояния') ; Открыть Case $msg = $contextOpen or $msg = $Dubl ShellExecute(StringTrimRight(GUICtrlRead(GUICtrlRead ($Dubl)),1)) ; Удаление Case $msg = $Delete If $folderList='' or $aArrOut='' Then ContinueLoop GUICtrlSetData($StatusBar, 'Удаление выполняется...') For $i = 1 to $aArrOut[0][0] If GUICtrlRead($aArrOut[$i][0],1)=1 And FileExists($aArrOut[$i][1]) Then FileDelete($aArrOut[$i][1]) GUICtrlDelete($aArrOut[$i][0]) $aArrOut[$i][0]='' $aArrOut[$i][1]='' EndIf Next _GUICtrlListView_SetColumnWidth($Dubl, 0, $LVSCW_AUTOSIZE) If _GUICtrlListView_GetColumnWidth($Dubl, 0)<480 Then _GUICtrlListView_SetColumnWidth($Dubl, 0, 480) GUICtrlSetData($StatusBar, 'Удаление завершено!') ; Поиск Case $msg = $Search If $folderList='' Then ContinueLoop If $aSizePath<>'' Then ; перед повторным поиском делаем очистку GUICtrlDelete ($Dubl) _Dubl() Sleep(50) $aSizePath = '' $aArr = '' $aArrT = '' $TempMD5 = '' $aArrOut = '' $aArrMD5 = '' EndIf GUICtrlSetData($StatusBar, 'Создание списка файлов...') $aSizePath = '' $timer = TimerInit() If StringLeft($folderList, 1)='|' Then $folderList = StringTrimLeft($folderList, 1) $aFolderList = StringSplit($folderList, '|') For $i = 1 To $aFolderList[0] ; выполняем поиск в цикле для каждого добавленного пути If FileExists($aFolderList[$i]) Then FileFindNextFirst($aFolderList[$i]) While 1 $tempname = FileFindNext() If $tempname = "" Then ExitLoop $aSizePath &= '|' & FileGetSize($tempname) & '|' & $tempname WEnd EndIf Next $aArrT = StringSplit(StringTrimLeft($aSizePath, 1), "|") ;создаём одномерный массив, имитацию двумерного массива. $aSizePath='1' ;очистка и индикатор выполненого поиска ;_ArrayDisplay($aArrT, "$aArrT") ; одномерный массив всех файлов (размер | путь) ;_ArrayDisplay($aArrT,"$aArrT",-1,-1,-1,-1, 'размер|путь') ; одномерный массив всех файлов (размер | путь) Dim $aArr[$aArrT[0] / 2 + 1][2] $aArr[0][0] = $aArrT[0] / 2 For $i = 1 To $aArrT[0] If Mod($i, 2) = 0 Then $aArr[$i / 2][0] = Int($aArrT[$i - 1]) $aArr[$i / 2][1] = $aArrT[$i] EndIf Next ; (массив | сортировка по возврастанию | начальный индекс сортировки | конечный | колонка сортировки) _ArraySort($aArr, 0, 1, $aArr[0][0], 0) ;_ArrayDisplay($aArr, "$aArr") ; сортированный двумерный массив всех файлов (размер | путь) $aArrOut = '' Dim $aArrOut[1][2] $a = 0 $0b = 0 $gp=0 $kol=0 $triger = 0 $triger2 = 0 $TempSize = '' For $i = 1 To $aArr[0][0] ; формирование временного массива файлов c совпадающими размерами, но вместа размера указан MD5 $kol+=1 If $aArr[$i][0] = $TempSize Then If $triger = 0 Then $MD5Path = '' $MD5Path &= '|' & _Crypt_HashFile($aArr[$i - 1][1], 0x00008003) & '|' & $aArr[$i - 1][1] EndIf $triger = 1 $MD5Path &= '|' & _Crypt_HashFile($aArr[$i][1], 0x00008003) & '|' & $aArr[$i][1] Else $triger = 0 EndIf ; переключение тригера для срабатывания обработки MD5 если совпадение существвали на последних элементах, чтоб правильно завершить цикл If $aArr[0][0]=2 and $triger = 1 Then $triger2 = 1 ; исключение для всего двух одинаковых файлов If $i = $aArr[0][0] Then $triger = 0 If $triger = 0 And $triger2 = 1 Then ; обработка временного массива с совпавшими размерами файлов ====================================== $aMD5PathT = StringSplit(StringTrimLeft($MD5Path, 1), "|") ;создаём одномерный массив, имитацию двумерного массива. ;_ArrayDisplay($aMD5PathT, "$aMD5PathT") ; сортированный массив всех файлов (размер | путь) ; конвертируем одномерный массив в двумерный. Dim $aArrMD5[$aMD5PathT[0] / 2 + 1][2] $aArrMD5[0][0] = $aMD5PathT[0] / 2 For $o = 1 To $aMD5PathT[0] If Mod($o, 2) = 0 Then $aArrMD5[$o / 2][0] = $aMD5PathT[$o - 1] $aArrMD5[$o / 2][1] = $aMD5PathT[$o] EndIf Next ;_ArrayDisplay($aArrMD5, "$aArrMD5- до сортировки") ; временный сортированный массив совпавших по размеру файлов, но с разными MD5 (MD5 | путь) _ArraySort($aArrMD5, 0, 1, $aArrMD5[0][0], 0) ;_ArrayDisplay($aArrMD5, "$aArrMD5- после сортировки") ; временный сортированный массив совпавших по размеру файлов, но с разными MD5 (MD5 | путь) ;=================================================================== ; вложенная, подобная копия основного алгоритма, с разницей MD5 вместо размера ; формирование временного массива совпадающих файлов $aArrOut по MD5 $0triger = 0 $0triger2 = 0 $TempMD5 = '' For $0i = 1 To $aArrMD5[0][0] If $a-$0b < 3 Then $a+=100 ReDim $aArrOut[$a][2] EndIf If $aArrMD5[$0i][0] = $TempMD5 Then If $0triger = 0 Then $0b += 1 $gp+=1 GUICtrlSetData($StatusBar, 'Всего: ' &$aArr[0][0]&', текущий: '&$kol &', группа: '&$gp &', добавлено: '&$0b &', время: '& Ceiling(TimerDiff($timer)/1000)&' сек, размер: '& Ceiling($aArr[$i][0]/1000)& 'кб' &@CRLF& $aArrMD5[$0i - 1][1]) GUICtrlCreateListViewItem( '---'&$gp&'---',$Dubl) GUICtrlSetColor(-1,0x777777) GUICtrlSetBkColor ( -1, 0xffffff ) $aArrOut[$0b][0] = GUICtrlCreateListViewItem($aArrMD5[$0i - 1][1],$Dubl) GUICtrlSetColor(-1,0xaa0000) $aArrOut[$0b][1] = $aArrMD5[$0i - 1][1] EndIf $0triger = 1 $0b += 1 GUICtrlSetData($StatusBar, 'Всего: ' &$aArr[0][0]&', текущий: '&$kol &', группа: '&$gp &', добавлено: '&$0b &', время: '& Ceiling(TimerDiff($timer)/1000) &' сек, размер: '& Ceiling($aArr[$i][0]/1000)& 'кб' &@CRLF& $aArrMD5[$0i][1]) $aArrOut[$0b][0] = GUICtrlCreateListViewItem($aArrMD5[$0i][1],$Dubl) GUICtrlSetState(-1,1) $aArrOut[$0b][1] = $aArrMD5[$0i][1] Else $0triger = 0 EndIf $TempMD5 = $aArrMD5[$0i][0] ;_GUICtrlListView_SetColumn($Dubl, 0, ' ', 480) Next EndIf ;================================================================================================================== If $triger = 1 Then $triger2 = 1 Else $triger2 = 0 EndIf $TempSize = $aArr[$i][0] _GUICtrlListView_SetColumnWidth($Dubl, 0, $LVSCW_AUTOSIZE) Next If _GUICtrlListView_GetColumnWidth($Dubl, 0)<480 Then _GUICtrlListView_SetColumnWidth($Dubl, 0, 480) ReDim $aArrOut[$0b+1][2] $aArrOut[0][0]=$0b If $0b = 0 Then GUICtrlSetData($StatusBar, 'Всего: ' &$aArr[0][0]&' файлов, дубликатов не найдено!') Else GUICtrlSetData($StatusBar, 'Всего: ' &$aArr[0][0]&', групп: '&$gp &', добавлено: '&$0b&', отмечено: '&$0b-$gp &', время: '& Ceiling(TimerDiff($timer)/1000)&' сек' &@CRLF& 'Готово!') EndIf ;_ArrayDisplay($aArrOut, "$aArrOut") ; Перезапуск Case $msg = $restart _restart() Case $msg = -3 _Crypt_Shutdown() Exit EndSelect WEnd ; добавлено из ListViewConstants.au3, для экономии размера скрипта Func _GUICtrlListView_SetColumnWidth($hWnd, $iCol, $iWidth) If $Debug_LV Then __UDF_ValidateClassName($hWnd, $__LISTVIEWCONSTANT_ClassName) If IsHWnd($hWnd) Then Return _SendMessage($hWnd, $LVM_SETCOLUMNWIDTH, $iCol, $iWidth) Else Return GUICtrlSendMsg($hWnd, $LVM_SETCOLUMNWIDTH, $iCol, $iWidth) EndIf EndFunc Func _GUICtrlListView_GetColumnWidth($hWnd, $iCol) If $Debug_LV Then __UDF_ValidateClassName($hWnd, $__LISTVIEWCONSTANT_ClassName) If IsHWnd($hWnd) Then Return _SendMessage($hWnd, $LVM_GETCOLUMNWIDTH, $iCol) Else Return GUICtrlSendMsg($hWnd, $LVM_GETCOLUMNWIDTH, $iCol, 0) EndIf EndFunc Func _Dubl() $GuiPos = WinGetPos($Gui) $Dubl = GUICtrlCreateListView(' ', 10, 150, $GuiPos[2]-26, $GuiPos[3]-251, $LVS_NOCOLUMNHEADER +$LVS_SHOWSELALWAYS, $LVS_EX_CHECKBOXES + $LVS_OWNERDRAWFIXED) GUICtrlSendMsg($Dubl, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_FULLROWSELECT, $LVS_EX_FULLROWSELECT) GUICtrlSendMsg($Dubl, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_TRACKSELECT, $LVS_EX_TRACKSELECT) GUICtrlSetBkColor(-1, 0xf0f0f0) ; 0xE0DFE3 - цвет стандартный серый GUICtrlSetResizing(-1, 7 + 32 + 64) EndFunc ;======================================== ; функция поиска всех файлов в каталоге (NIKZZZZ) 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 Func _restart() Local $sAutoIt_File = @TempDir & "\~Au3_ScriptRestart_TempFile.au3" Local $sRunLine, $sScript_Content, $hFile $sRunLine = @ScriptFullPath If Not @Compiled Then $sRunLine = @AutoItExe & ' /AutoIt3ExecuteScript ""' & $sRunLine & '""' If $CmdLine[0] > 0 Then $sRunLine &= ' ' & $CmdLineRaw $sScript_Content &= '#NoTrayIcon' & @CRLF & _ 'While ProcessExists(' & @AutoItPID & ')' & @CRLF & _ ' Sleep(10)' & @CRLF & _ 'WEnd' & @CRLF & _ 'Run("' & $sRunLine & '")' & @CRLF & _ 'FileDelete(@ScriptFullPath)' & @CRLF $hFile = FileOpen($sAutoIt_File, 2) FileWrite($hFile, $sScript_Content) FileClose($hFile) Run(@AutoItExe & ' /AutoIt3ExecuteScript "' & $sAutoIt_File & '"', @ScriptDir, @SW_HIDE) Sleep(1000) Exit EndFunc ;==>_restart Func _Quit() Exit EndFunc ;==>_Quit Func _About() GUISetState(@SW_HIDE, $Gui) $font="Arial" $Gui1 = GUICreate("О программе", 270, 180, -1, -1, -1, 0x00000080) GUISetBkColor (0xf8c848) GUICtrlCreateLabel('Search duplicates', 0, 20, 270, 23, 0x01) GUICtrlSetFont (-1,15, 600, -1, $font) GUICtrlSetColor(-1,0xa21a10) GUICtrlCreateLabel('поиск дубликатов файлов', 0, 49, 270, 46, 0x01) GUICtrlSetFont (-1,13, 600, -1, $font) GUISetFont (9, 600, -1, $font) GUICtrlSetColor(-1,0xa21a10) GUICtrlCreateLabel('Версия 0.1 от 9.07.2010', 55, 100, 210, 17) GUICtrlCreateLabel('Сайт:', 55, 115, 40, 17) $url=GUICtrlCreateLabel('http://azjio.ucoz.ru', 92, 115, 170, 17) GUICtrlSetCursor(-1, 0) GUICtrlSetColor(-1, 0x0000ff) GUICtrlCreateLabel('WebMoney: R939163939152', 55, 130, 210, 17) GUICtrlCreateLabel('Copyright AZJIO © 2010', 55, 145, 210, 17) GUISetState(@SW_SHOW, $Gui1) $msg = $Gui1 While 1 $msg = GUIGetMsg() Select Case $msg = $url ShellExecute ('http://azjio.ucoz.ru') Case $msg = -3 $msg = $Gui GUIDelete($Gui1) GUISetState(@SW_SHOW, $Gui) ExitLoop EndSelect WEnd EndFunc |