Search code examples
filepowershellcomparedirectorylast-modified

Compare folders content based on LastWriteTime (last-modified), in Windows 7


I need to compare the files (that have the same names) of two different folders (and their subfolders) based on their LastWriteTime property, so I can find out if there were modifications (and if yes, then which file on which folder is the newest).

In sum: all I want to know is if there are more recently modified copies of files in the second folder.

I'm trying to run a Powershell 2.0 script to do this, but it seems I have no clue of what I'm doing:

$orig = Get-ChildItem -Recurse -path L:\original-files\
$backup = Get-ChildItem -Recurse -path I:\backup-files\

Compare-Object $orig $backup -Property LastWriteTime

Which outputs this:

...
Report -- XXXXXXXX, Meeting with suppl... 23/02/2015 17:45:38                     =>                                     
Report -- XXXXXXXX, Meeting with suppl... 17/11/2015 20:29:04                     =>                                     
Report -- XXXXXXXX, Meeting with suppl... 06/08/2015 22:39:06                     =>                                     
Report -- XXXXXXXX, Meeting with suppl... 07/05/2015 03:43:24                     =>                                     
Report -- XXXXXXXX, Meeting with suppl... 26/06/2015 15:22:36                     =>                                     
Report -- XXXXXXXX, Meeting with suppl... 26/06/2015 17:03:48                     =>                                     
Report -- XXXXXXXX, Meeting with suppl... 13/09/2015 15:41:38                     =>                                     
Report -- XXXXXXXX, Meeting with suppl... 21/06/2015 23:28:06                     =>                                     
Report -- XXXXXXXX, Meeting with suppl... 22/02/2015 01:23:58                     =>                                     
Report -- XXXXXXXX, Meeting with suppl... 11/12/2015 00:50:52                     =>                                     
Report -- XXXXXXXX, Meeting with suppl... 30/10/2015 05:27:48                     <=                                     
Report -- XXXXXXXX, Meeting with suppl... 31/05/2015 17:46:08                     <= 
...

So, this script has 2 problems:

  1. I don't really know the names of the files, because they get truncated.
  2. I still don't know which file is the last modified, since I get most of the times the same file names (not the path name), but with inverted SideIndicator signs, appearing in the list 2 times (rarely 1 or 3 times) (I think this happens because I might have copies of the same file in different subfolders). For example:

    example.docx     25/12/2015 15:15:05              =>
    example.docx     23/12/2015 12:36:03              <=
    

where are these two files, that have the same name, located? And what should the "=>" and the "<=" signs mean in this context, where I have the same file name repeated in the list with an inverted sign?

I just wasted my day trying to this. Please help! I'm on Win 7 64 bit.

Thank you!!!


PS: I jut found out that appending | Format-List (i.e., Compare-Object $orig $backup -Property LastWriteTime | Format-List) displays correctly the full name of the file, but not its path. Therefore it's useless to know that 'Example.docx' appears on the list 2 times with the '=>' sign, and 1 time with the '<=' sign.

PS2: I tried changing

$orig = Get-ChildItem -Recurse -path L:\original-files\
$backup = Get-ChildItem -Recurse -path I:\backup-files\

to

$orig = Get-ChildItem -Recurse -path L:\original-files\ | Format-List -Property Name, Fullname, LastWriteTime
$backup = Get-ChildItem -Recurse -path I:\backup-files\ | Format-List -Property Name, Fullname, LastWriteTime

But diff $orig $backup - property lastwritetime | format-list outputs:

lastwritetime :
SideIndicator : =>

lastwritetime :
SideIndicator : =>

lastwritetime :
SideIndicator : =>

lastwritetime :
SideIndicator : =>

lastwritetime :
SideIndicator : =>

lastwritetime :
SideIndicator : =>

lastwritetime :
SideIndicator : =>

lastwritetime :
SideIndicator : =>

lastwritetime :
SideIndicator : =>

Solution

  • So, after being beaten up by PS, I wrote this unefficient "javascript-esque" script for Powershell 2.0. There is no need to change preferences etc., just start the console and paste this entire chunk of code:

    $sourcePath = "C:\test1"
    $targetPath = "C:\test2"
    
    $source = Get-ChildItem -LiteralPath $sourcePath -Recurse | where { ! $_.PSIsContainer }
    $target = Get-ChildItem -LiteralPath $targetPath -Recurse | where { ! $_.PSIsContainer }
    
    
    $sourceGroup = $source | group-object -property name
    $targetGroup = $target | group-object -property name
    $includedOrNot = Compare-Object -ReferenceObject $sourceGroup -DifferenceObject $targetGroup -Property Name -Passthru
    $excludedSource = $includedOrNot | where-object { $_.SideIndicator -eq "=>"}
    $excludedTarget = $includedOrNot | where-object { $_.SideIndicator -eq "<="}
    
    $differentTime = Compare-Object -ReferenceObject $Source -DifferenceObject $Target -Property LastWriteTime -PassThru
    
    $filesInTarget = @()
    
    $buffer = @()
    foreach ($i in $differentTime) {$buffer += , @($i.name, $i.lastwritetime, $i.fullname)}
    
    for ($i = 0; $i -ne $buffer.length; $i++) {
    $bufname = $buffer[$i][0] ; $buftime = $buffer[$i][1]; foreach ($ii in $buffer) {
    if ($ii[0] -eq $bufname -and $ii[1] -gt $buftime -and $ii[2].startswith($targetPath)) {
    $filesInTarget += , @($ii)
    }
    }
    }
    
    $newerFiles = @()
    foreach ($iii in $filesInTarget) {$newerFiles+= $iii[-1]}
    
    echo "`n`n***START`n`n`nAbsent files in SOURCE folder:`n`n"; $excludedSource |format-list;`
    "`n`nAbsent files in TARGET folder:`n"; $excludedTarget |format-list;`
    "`n`n`n`n`nNEWER FILES IN TARGET FOLDER:`n`n"; $filesInTarget | format-list;`
    "`n`n`n`n`n`n`n`n`n`nSUMMARY:`n`nNumber of files absent in SOURCE: " + $excludedSource.count;`
    $excludedSource | Format-Table Count, Name -Autosize;`
    "`nNumber of files absent in TARGET: " + $excludedTarget.count;`
    $excludedTarget | Format-Table Count, Name -Autosize;`
    "`nNewer files in target folder:", $newerFiles, "`n`n***END`n"
    
    #END OF FILE
    

    It shows if there are more recently altered homonymous files in the Target folder and subfolders (compared to the Source folder and subfolders). It also tells if there are files in one folder, but no files with the same name in the other one.

    Thanks a lot for DarkLite1 for putting me on the right path!