PoshCode Archive  Artifact [7e02a00458]

Artifact 7e02a00458a1db44b277b1049f0ee3ee5915c838884d30ff6110ebfef57fef9c:

  • File Compare-Folders.ps1 — part of check-in [375b250ede] at 2018-06-10 13:45:44 on branch trunk — This PowerShell Script will compare all of the files in the same directory on two or more different computers. It will compute the MD5 hash of a file and use that to compare (user: Brian size: 3399)

# encoding: ascii
# api: powershell
# title: Compare-Folders.ps1
# description: This PowerShell Script will compare all of the files in the same directory on two or more different computers. It will compute the MD5 hash of a file and use that to compare
# version: 1.0.0
# type: script
# author: Brian
# license: CC0
# function: Reduce-Set
# x-poshcode-id: 4781
# x-archived: 2016-10-25T20:25:47
# x-published: 2016-01-08T14:45:00
#
#
#require -version 2.0
<#
.SYNOPSIS
This PowerShell Script will compare all of the files in the same directory on two or more different computers. It will compute the MD5 hash of a file and use that to compare

.DESCRIPTION
Version - 1.0.0
This PowerShell Script will compare all of the files in the same directory on two or more different computers

.EXAMPLE
.\Compare-Folders.ps1 -computers @("srv-1","srv-2") -path "D:\Inetpub" 

.PARAMETER Computers
Specifies the computers to compare. Mandatory parameter

.PARAMETER Path
Specifies the folder to check on the computers

.PARAMETER csv
Full Path to CSV file. If not passed, then results will display to the screen

.NOTES

#>

[CmdletBinding(SupportsShouldProcess=$true)]
param (
	[Parameter(Mandatory=$true)] [string[]] $computers,
	[Parameter(Mandatory=$true)] [string] $path, 
    [string] $csv
)

function Reduce-Set
{
	param(
		[Parameter(ValueFromPipeline=$true)]
   		[HashTable] $ht
	)
	
	begin { 
		Set-Varible -Name differences -Values @()
	}
	process {		
		Write-Verbose "Comparing Keys . . ."				
		foreach ( $key in $ht.Keys ) {
			if( $ht[$key].Count -eq 1 ) {		
				$differences += (New-Object PSObject -Property @{
					File = $ht[$key] | Select -ExpandProperty Name
					System = $ht[$key] | Select -ExpandProperty System
					Hash = $ht[$key] | Select -ExpandProperty FileHash
				})
			} 
			elseif( ($ht[$key] | Select -Unique -ExpandProperty FileHash).Count -ne 1 )	{
				foreach( $diff in $ht[$key] ) {
					$differences += (New-Object PSObject -Property @{
						File =  $diff.Name
						System = $diff.System
						Hash = $diff.FileHash
					})
				}
			}
		}
		
	}
	end { 
		return $differences
	}
}

$map = {
	param ( [string] $directory )
 	
	function Get-Hash {
        param([string] $file)
		$fileStream = [system.io.file]::openread($file)
	    $hasher = [System.Security.Cryptography.HashAlgorithm]::create("md5")
	    $hash = $hasher.ComputeHash($fileStream)
	    $fileStream.Close()
	    $md5 = ([system.bitconverter]::tostring($hash)).Replace("-","")
	    return ( $md5 ) 
    }

    Set-Variable -Name files -Value @()
	
	Write-Verbose ("Working on - {0}" -f $ENV:COMPUTERNAME)

	foreach( $file in (Get-ChildItem $directory -Recurse | Where { $_.PSIsContainer -eq $false } ) ) {
		$files += New-Object PSObject -Property @{
            Name = $file.FullName
			System = $ENV:COMPUTERNAME
            FileHash = (Get-Hash $file.FullName)
		}
	}
	return $files
} 

function main
{
	$results = Invoke-Command -ComputerName $computers -ScriptBlock $map -ArgumentList $path | 
        Select Name, FileHash, System |
        Group-Object -Property Name -AsHashTable |
        Reduce-Set
    	
	if( ![string]::IsNullOrEmpty($csv) ) {
		$results | Export-Csv -Encoding Ascii -NoTypeInformation $csv
		Invoke-Item $csv
	}
	else {
		return $results
	}
}
main