Deye Posted May 10, 2019 Share Posted May 10, 2019 (edited) Time to clean up my downloads folder So I made this little Demo that gets a preview of what duplicate files or folders with prefixes of "\(.*\)" or "?-?Copy" are spread around My downloads folder Modern browsers falt is @not giving the Two needed separate options: 1 replace existing file ? 2 Download and create the file prefixed with a (#) (Default ..) Anyways .. Spoiler expandcollapse popup#include <WinAPIShellEx.au3> #include <File.au3> $pattern = "*(?)*;*(??)*;*?-?Copy*" $FOLDER = _WinAPI_ShellGetKnownFolderPath($FOLDERID_Downloads) ConsoleWrite(@LF & " [Duplicate: File Clutter Preview] " & @LF) $aArray = _FileListToArrayRec($FOLDER, $pattern, 1, $FLTAR_NORECUR, $FLTAR_SORT, 2) Local $aToDelete[""], $1, $2, $sFile, $sFileBareFormat, $istart, $index, $sArray = _ArrayToString($aArray, @LF, 1) For $i = UBound($aArray) - 1 To 1 Step -1 $sFile = StringRegExpReplace($aArray[$i], "\s\(.*\)|\(.*\)|( - Copy)", "") $sFileBareFormat = StringRegExpReplace($sFile, "^.*\\|\..*$", "") $aFiles = StringRegExp($sArray, "(?i:.*\\" & $sFileBareFormat & ")+[\s-()\QCopy\E].*", 3) If Not IsArray($aFiles) Then ; if the StringRegExp is not optimized to get all variations If Not FileExists($sFile) Then ConsoleWrite(" Renaming " & $aArray[$i] & " to " & $sFile & @LF) ;FileMove($aFiles[$i], $sFile, 9) ElseIf Compare_2($aArray[$i]) == Compare_2($sFile) Then ConsoleWrite(" " & $aArray[$i] & " = " & $sFile & @LF) _ArrayAdd($aToDelete, $aArray[$i]) EndIf ContinueLoop ElseIf UBound($aFiles) = 1 Then If Not FileExists($sFile) Then ConsoleWrite(" Renaming " & $aFiles[0] & " to " & $sFile & @LF) ;FileMove($aFiles[0], $sFile, 9) ElseIf Compare_2($aFiles[0]) == Compare_2($sFile) Then ConsoleWrite(" " & $aFiles[0] & " = " & $sFile & @LF) _ArrayAdd($aToDelete, $aFiles[0]) EndIf ContinueLoop EndIf If UBound($aFiles) > 1 Then $i -= UBound($aFiles) - 1 Local $aArray2D[UBound($aFiles)][3] For $j = 0 To UBound($aFiles) - 1 $aArray2D[$j][0] = $aFiles[$j] $aArray2D[$j][1] = FileGetTime($aFiles[$j], 1, 1) $aArray2D[$j][2] = StringRegExp($aFiles[$j], "^.*\.") ? StringRegExpReplace($aFiles[$j], "^.*\.", ".$1") : "False" Next Local $sFileHash, $index = 0, $istart = $index, $KHash Do _ArraySort($aArray2D, 1, Default, Default, 2) ;Get indexes of matching extentions $istart = $index $index = _ArraySearch($aArray2D, $aArray2D[$istart + 1][2], $istart + 1, Default, 1, Default, 0, 2) If @error Then ExitLoop $istart += $istart > 0 ? 1 : 0 If $istart = $index Then If UBound($aArray2D) - 1 > $index Then $index += 1 ContinueLoop EndIf _ArraySort($aArray2D, 0, $istart, $index, 1) ;Sort indexes to latest file For $k = $index To $istart Step -1 If Not FileExists($aArray2D[$k][0]) Then ContinueLoop $sFile = StringRegExpReplace($aArray2D[$k][0], "\s\(.*\)|\(.*\)|( - Copy)|\..*$", "") $sFile &= $aArray2D[$k][2] = "False" ? "" : $aArray2D[$k][2] If Not FileExists($sFile) Then ConsoleWrite(" Renaming latest file " & $aArray2D[$k][0] & " to " & $sFile & @LF) FileCopy($aArray2D[$k][0], StringRegExpReplace($sFile, "(^.*\\)(.*)", "\1")) ;FileMove($aArray2D[$k][0], $sFile, 9) ContinueLoop EndIf $sFileHash = Compare_2($sFile) $KHash = Compare_2($aArray2D[$k][0]) For $f = $k - 1 To $istart Step -1 If Not FileExists($aArray2D[$f][0]) Then ContinueLoop If $KHash = Compare_2($aArray2D[$f][0]) Then $1 = StringLen($aArray2D[$f][0]) > StringLen($aArray2D[$k][0]) ? $aArray2D[$f][0] : $aArray2D[$k][0] $2 = ($1 = $aArray2D[$f][0] ? $aArray2D[$k][0] : $aArray2D[$f][0]) ConsoleWrite(" " & $1 & " = " & $2 & @LF) _ArrayAdd($aToDelete, $1) ;FileDelete($1) If $sFileHash = $KHash Then ConsoleWrite(" " & $2 & " = " & $sFile & @LF) ;FileDelete($2) _ArrayAdd($aToDelete, $2) EndIf ExitLoop EndIf Next Next Until $index = UBound($aArray2D) - 1 EndIf Next _ArrayDisplay($aToDelete, "Files To Delete") Func Compare_2($File = "") ;~ Return _CRC32ForFile($File) & _MD5ForFile($File) ;add this back to get real dups when done testing Return FileGetSize($File) EndFunc ;==>Compare_2 Func _MD5ForFile($sFile) ; by trancexx Local $a_hCall = DllCall("kernel32.dll", "hwnd", "CreateFileW", "wstr", $sFile, "dword", 0x80000000, "dword", 3, "ptr", 0, "dword", 3, "dword", 0, "ptr", 0) If @error Or $a_hCall[0] = -1 Then Return SetError(1, 0, "") EndIf Local $hFile = $a_hCall[0] $a_hCall = DllCall("kernel32.dll", "ptr", "CreateFileMappingW", "hwnd", $hFile, "dword", 0, "dword", 2, "dword", 0, "dword", 0, "ptr", 0) If @error Or Not $a_hCall[0] Then DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFile) Return SetError(2, 0, "") EndIf DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFile) Local $hFileMappingObject = $a_hCall[0] $a_hCall = DllCall("kernel32.dll", "ptr", "MapViewOfFile", "hwnd", $hFileMappingObject, "dword", 4, "dword", 0, "dword", 0, "dword", 0) If @error Or Not $a_hCall[0] Then DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject) Return SetError(3, 0, "") EndIf Local $pFile = $a_hCall[0] Local $iBufferSize = FileGetSize($sFile) Local $tMD5_CTX = DllStructCreate("dword i[2];" & "dword buf[4];" & "ubyte in[64];" & "ubyte digest[16]") DllCall("advapi32.dll", "none", "MD5Init", "ptr", DllStructGetPtr($tMD5_CTX)) If @error Then DllCall("kernel32.dll", "int", "UnmapViewOfFile", "ptr", $pFile) DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject) Return SetError(4, 0, "") EndIf DllCall("advapi32.dll", "none", "MD5Update", "ptr", DllStructGetPtr($tMD5_CTX), "ptr", $pFile, "dword", $iBufferSize) If @error Then DllCall("kernel32.dll", "int", "UnmapViewOfFile", "ptr", $pFile) DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject) Return SetError(5, 0, "") EndIf DllCall("advapi32.dll", "none", "MD5Final", "ptr", DllStructGetPtr($tMD5_CTX)) If @error Then DllCall("kernel32.dll", "int", "UnmapViewOfFile", "ptr", $pFile) DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject) Return SetError(6, 0, "") EndIf DllCall("kernel32.dll", "int", "UnmapViewOfFile", "ptr", $pFile) DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject) Local $sMD5 = Hex(DllStructGetData($tMD5_CTX, "digest")) Return SetError(0, 0, $sMD5) EndFunc ;==>_MD5ForFile Func _CRC32ForFile($sFile) ; by trancexx Local $a_hCall = DllCall("kernel32.dll", "hwnd", "CreateFileW", "wstr", $sFile, "dword", 0x80000000, "dword", 3, "ptr", 0, "dword", 3, "dword", 0, "ptr", 0) If @error Or $a_hCall[0] = -1 Then Return SetError(1, 0, "") EndIf Local $hFile = $a_hCall[0] $a_hCall = DllCall("kernel32.dll", "ptr", "CreateFileMappingW", "hwnd", $hFile, "dword", 0, "dword", 2, "dword", 0, "dword", 0, "ptr", 0) If @error Or Not $a_hCall[0] Then DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFile) Return SetError(2, 0, "") EndIf DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFile) Local $hFileMappingObject = $a_hCall[0] $a_hCall = DllCall("kernel32.dll", "ptr", "MapViewOfFile", "hwnd", $hFileMappingObject, "dword", 4, "dword", 0, "dword", 0, "dword", 0) If @error Or Not $a_hCall[0] Then DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject) Return SetError(3, 0, "") EndIf Local $pFile = $a_hCall[0] Local $iBufferSize = FileGetSize($sFile) Local $a_iCall = DllCall("ntdll.dll", "dword", "RtlComputeCrc32", "dword", 0, "ptr", $pFile, "int", $iBufferSize) If @error Or Not $a_iCall[0] Then DllCall("kernel32.dll", "int", "UnmapViewOfFile", "ptr", $pFile) DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject) Return SetError(4, 0, "") EndIf DllCall("kernel32.dll", "int", "UnmapViewOfFile", "ptr", $pFile) DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject) Local $iCRC32 = $a_iCall[0] Return SetError(0, 0, Hex($iCRC32)) EndFunc ;==>_CRC32ForFile Deye Edited December 14, 2019 by Deye Typos Link to comment Share on other sites More sharing options...
Deye Posted May 10, 2019 Author Share Posted May 10, 2019 (edited) Updated the $pattern so it will get any files without extensions too None intended "Bug" left over : Changed FileListToArrayRec to use $FLTAR_NORECUR to read only from the root Dir (Files part) Edited May 10, 2019 by Deye Link to comment Share on other sites More sharing options...
Deye Posted May 16, 2019 Author Share Posted May 16, 2019 Next Update : This will probably need some extra proofing and\or method cleanups here and there So far, It will be good to know how does it work for you does it get all duplicates @ any "presented folder" ? Thanks Deye Link to comment Share on other sites More sharing options...
Deye Posted December 9, 2019 Author Share Posted December 9, 2019 a quick fix to a small typo bug I've just noticed upon reviewing this again - Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now