Sebiix3 Posted October 12, 2021 Posted October 12, 2021 Hey guys, I'm once again come to a problem, or I do not quite know how to do it... I would like to compare 2 folders and their files (+ subfolders) with each other. Would be enough to compare date-modified for each file. Both folders contain mostly the same files. I would like to get an array, where all filenames are contained, which differ in the date (date motified) from each other. E.g. in both folders is the file "test.txt". In folder 1 with the date 12.10.2021 19:25:02, but in folder 2 a newer date. Then the "text.txt" should be in the array because it is newer than in folder 1. Additionally, I would like to detect "new" files. So those that are already in folder 2, but not in folder 1 get into the array as well. _FileListArrayToRec seems to be what I need and it also looks subfolders. Unfortunately I don't know how to do this.... Could someone help me out on this? Thanks in advance!
seadoggie01 Posted October 12, 2021 Posted October 12, 2021 I've personally used SMF, but it won't put the files in an array, instead displaying them in a GUI Alternately, you can start by using some variation of this: Spoiler expandcollapse popup#include <File.au3> Func Main() ; Get Files of directory1 (DirModifiedTime) ; Get Files of directory2 (DirModifiedTime) ; For each file in Directory1 ; If found in Directory2 then (_ArraySearch) ; If modifiedDate in Dir1 > Dir2 ; Add to array (_ArrayAdd) ; Else ; Do nothing? ; Else ; Do nothing? ; Next EndFunc ; Returns 1-based 2D array of [<File/Dir>, <ModifiedDate>] ; Requires #include <File.au3> ; See example output with: _ArrayDisplay(DirModifiedTime(@UserProfileDir & "\Documents\", Default, Default, True)) Func DirModifiedTime($sDir, $sFilter = Default, $iFlag = Default, $bReturnPath = Default) ; Requires #include <FileConstants.au3> ; Get all files Local $aFiles = _FileListToArray($sDir, $sFilter, $iFlag, $bReturnPath) If @error Then Return SetError(1, 0, False) Local $aFileModified[UBound($aFiles)][2] $aFileModified[0][0] = $aFiles[0] For $i=1 To UBound($aFiles) - 1 $aFileModified[$i][0] = $aFiles[$i] ; Get the last modified date in a string $aFileModified[$i][1] = FileGetTime($aFiles[$i], $FT_MODIFIED, $FT_STRING) Next Return $aFileModified EndFunc All my code provided is Public Domain... but it may not work. Use it, change it, break it, whatever you want. Spoiler My Humble Contributions:Personal Function Documentation - A personal HelpFile for your functionsAcro.au3 UDF - Automating Acrobat ProToDo Finder - Find #ToDo: lines in your scriptsUI-SimpleWrappers UDF - Use UI Automation more Simply-erKeePass UDF - Automate KeePass, a password managerInputBoxes - Simple Input boxes for various variable types
kjpolker Posted October 12, 2021 Posted October 12, 2021 (edited) That's a tall order. Here is a sample code to get you started: #include <Array.au3> #include <File.au3> #include <MsgBoxConstants.au3> #include <FileConstants.au3> $Dir1 = @DesktopDir $Dir2 = "Directory\To\Folder" Global $Stamp[0] Example() Func Example() ;Retrives all file(s) in directory 1 as a full path and sorts them alphabetically. Local $FileArray = _FileListToArrayRec($Dir1, "*", $FLTAR_FILES, $FLTAR_NORECUR, $FLTAR_SORT, $FLTAR_FULLPATH) ;Uncomment to display the files found. ;~ _ArrayDisplay($FileArray, "Directory 1") If @error = 1 Then MsgBox($MB_SYSTEMMODAL, "", "Path is invalid.") Exit ElseIf @error = 4 Then MsgBox($MB_SYSTEMMODAL, "", "No file(s) were found.") Exit EndIf For $i = 1 to UBound($FileArray) - 1 ;Retrieves the last modified date of each element. $FileModArray = FileGetTime($FileArray[$i]) ;Adds them to a new array in the format of 'MM/DD/YY @ ##:##:##' _ArrayAdd($Stamp, $FileModArray[1] & "/" & $FileModArray[2] & "/" & $FileModArray[0] & " @ " & $FileModArray[3] & ":" & $FileModArray[4] & ":" & $FileModArray[5], 0) Next ;Uncomment to display the time stamps of each file. ;~ _ArrayDisplay($Stamp, "Directory 1") EndFunc This will return the files and modified dates in the directory of your choosing (currently set to Desktop). From here I would mimic the process for Directory 2 and compare the values of each element. If any differences are found then maintain the integrity of the element in the arrays. Such as: ;Select largest array If UBound($FileArray1) > UBound($FileArray2) Then $length = UBound($FileArray1) ElseIf UBound($FileArray1) < UBound($FileArray2) Then $length = UBound($FileArray2) Else ;Arrays must be same size $length = UBound($FileArray1) EndIf ;If directories contain the same files and modified dates delete them from array. For $i = 1 To $length ;Search arrays for similar data, if found delete them. $found = _ArraySearch($FileModArray2, $FileModArray1[$i]) If $found <> -1 Then _ArrayDelete($FileArray1, $found) _ArrayDelete($FileArray2, $found) _ArrayDelete($FileModArray1, $found) _ArrayDelete($FileModArray2, $found) Else ConsoleWrite($Array1[$i] & " not found" & @CRLF) EndIf Next EndIf ;The above will need some tweaking to ensure the proper elements are being deleted from $FileArray, perhaps you can just insert the modified dates into the array strings and compare them in whole (C:\Path\to\first\file.txt MM/DD/YYYY @ ##:##:##) and compare just two arrays deleting all similar instances. Hopefully this gets you started and you can look into some of the logic and functions available to cross the finish line. Edited October 12, 2021 by kjpolker
Subz Posted October 13, 2021 Posted October 13, 2021 Since you're really only looking at changes in folder 2 then you should only have to compare the contents of Folder2 against Folder1 (or have I read it wrong), for example: #include <Array.au3> #include <File.au3> Local $sFolder1 = @ScriptDir & "\Folder1" Local $sFolder2 = @ScriptDir & "\Folder2" Local $aFolder2 = _FileListToArrayRec($sFolder2, "*", 1, 1, 0, 1) If @error Then Exit MsgBox(16, "Error", "No files found") _ArrayDisplay($aFolder2, "Before") For $i = $aFolder2[0] To 1 Step - 1 _CompareTimeStamp($aFolder2[$i]) If @error Then _ArrayDelete($aFolder2, $i) Next $aFolder2[0] = UBound($aFolder2) - 1 _ArrayDisplay($aFolder2, "After") Func _CompareTimeStamp($_sFilename) Local $sFile1 = FileGetTime($sFolder1 & "\" & $_sFilename, 0, 1) If @error Then Return SetError(0) ;~ File doesn't exist in Folder1 so leave in array Local $sFile2 = FileGetTime($sFolder2 & "\" & $_sFilename, 0, 1) If $sFile2 > $sFile1 Then Return SetError(0) ;~ File2 is newer than File1 so leave in array Return SetError(1) EndFunc
Musashi Posted October 13, 2021 Posted October 13, 2021 Just for your information : This question was (cross-)posted by the user @Sebiix3 in the German forum as well. A nice solution approach has already been provided there by @Bitnugger , see : https://autoit.de/thread/87477-2-folder-und-deren-dateien-miteinander-vergleichen/?postID=704897#post704897 "In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move."
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