function Compare-File { <# .SYNOPSIS Compares two files, displaying differences in a manner similar to traditional console-based diff utilities. #> param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] $CompareFrom, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] $CompareTo, [Parameter(Mandatory = $false)] [int]$SurroundingLines = 5, [switch]$Porcelain ) $CompareFrom = (Resolve-Path $CompareFrom).Path $CompareTo = (Resolve-Path $CompareTo).Path $totalFormatWidth = 14 # 5 x2 for numbers, 4 for column separators $screenWidth = Get-ConsoleDisplayWidth $fixedWidth = ($screenWidth - ($screenWidth % 2) - $totalFormatWidth) / 2 $fileHeaderPrint = " " $fileHeaderFrom = Select-RightSubstringWithPadLeft -String $CompareFrom -Length ($screenWidth - 10) $fileHeaderTo = Select-RightSubstringWithPadLeft -String $CompareTo -Length ($screenWidth - 10) ## Get the content from each file $contentFrom = Get-Content -Path $CompareFrom $contentTo = Get-Content -Path $CompareTo ## Compare the two files. Get-Content annotates output objects with ## a 'ReadCount' property that represents the line number in the file ## that the text came from. $comparedLines = Compare-Object -ReferenceObject $contentFrom -DifferenceObject $contentTo -IncludeEqual | Sort-Object { $line.InputObject.ReadCount } if ($comparedLines.Count -eq 0) { if (!$Porcelain) { "$fileHeaderPrint : $fileHeaderFrom : $fileHeaderTo" Write-Host "Contents were the same" } return } $shortestFileLength = [Math]::Max($contentFrom.Length, $contentTo.Length) $lineNumberColor = $PSStyle.ForegroundColor.LightCyan $reset = $PSStyle.Reset $diffLeftColor = $PSStyle.ForegroundColor.LightRed $diffRightColor = $PSStyle.ForegroundColor.Green <# $lineNumber = 0 $fromResults = @{} $toResults = @{} $lineNumbers = @() foreach ($line in $comparedLines) { $lineNumber = $line.InputObject.ReadCount if($line.SideIndicator -eq "=>") { $lineNumbers += $lineNumber $fromResults["$lineNumber"] = $line.InputObject } elseif($line.SideIndicator -eq "<=") { $lineNumbers += $lineNumber $toResults["$lineNumber"] = $line.InputObject } else { $fromResults["$lineNumber"] = $line.InputObject $toResults["$lineNumber"] = $line.InputObject } } #> $compareStart = $comparedLines[0].InputObject.ReadCount $compareEnd = $comparedLines[-1].InputObject.ReadCount $lineNumbers = @() $leftLineNumber = 1 $rightLineNumber = 1 $printLines = @{} $currentLineCounter = 1 for ($i = 1; $i -le $comparedLines.Count; $i++) { $lines = $comparedLines.Where({$_.InputObject.ReadCount -eq $i}) if ($null -eq $lines -or $lines.Count -eq 0) { continue } $leftLine = $lines.Where({$_.SideIndicator -eq '=>'})[0].InputObject $rightLine = $lines.Where({$_.SideIndicator -eq '<='})[0].InputObject $sameLine = $lines.Where({$_.SideIndicator -eq '=='})[0].InputObject $printLine = @{ Line = $currentLineCounter; LeftLine = $null; RightLine = $null; LeftLineNumber = $null; RightLineNumber = $null; } $triggerSave = $false if ($null -ne $leftLine) { $printLine.LeftLine = $leftLine $printLine.LeftLineNumber = $leftLineNumber $triggerSave = $true $leftLineNumber += 1 } if ($null -ne $rightLine) { $printLine.RightLine = $rightLine $printLine.RightLineNumber = $rightLineNumber $triggerSave = $true $rightLineNumber += 1 } if ($triggerSave) { $printLines[$currentLineCounter] = $printLine $lineNumbers += $currentLineCounter } if ($null -ne $sameLine) { $triggerSave = $true $printLine = @{ Line = $currentLineCounter; LeftLine = $sameLine; RightLine = $sameLine; LeftLineNumber = $leftLineNumber; RightLineNumber = $rightLineNumber; } $rightLineNumber += 1 $leftLineNumber += 1 } if ($triggerSave) { $printLines[$currentLineCounter] = $printLine $currentLineCounter += 1 } <#continue if ($lines.Where({$_.SideIndicator -eq "=="}).Count -gt 0) { $left["$i"] = $lines[0].InputObject $right["$i"] = $lines[0].InputObject } if ($lines.Where({$_.SideIndicator -eq '=>'}).Count -gt 0) { $left["$i"] = $lines.Where({$_.SideIndicator -eq '=>'})[0].InputObject $lineNumbers += $i } if ($lines.Where({$_.SideIndicator -eq '<='}).Count -gt 0) { $right["$i"] = $lines.Where({$_.SideIndicator -eq '<='})[0].InputObject $lineNumbers += $i }#> } if ($lineNumbers.Count -gt 0) { $lineNumbers = $lineNumbers | Sort-Object | Get-Unique $groups = Group-Numbers -Values $lineNumbers <#foreach($group in $groups) { Write-Host ($group -join ',') }#> $printedLineNumbers = @() $headerBoxContent = @() $headerBoxContent += "Left: $($fileHeaderFrom.Trim())" $headerBoxContent += "Right: $($fileHeaderTo.Trim())" $headerBox = Show-Box -Content $headerBoxContent -Padding 0 $print = @($headerBox) $groupsCount = $groups.Count $groupCounter = 1 foreach ($group in $groups) { $first = $group[0] - $SurroundingLines if ($first -lt 1) { $first = 1 } $last = $group[-1] + $SurroundingLines if ($last -gt $shortestFileLength) { $last = $shortestFileLength } for ($i = $first; $i -le $last; $i++) { if ($printedLineNumbers -contains $i) { continue } $line = $printLines[$i] $left = $line.LeftLine $right = $line.RightLine if ($lineNumbers -contains $i) { # We need to print this as a difference $diffLeftColor = $PSStyle.ForegroundColor.LightRed $leftLineLead = " -" if ([string]::IsNullOrWhiteSpace($left)) { $leftLineLead = "" } $diffRightColor = $PSStyle.ForegroundColor.Green $rightLineLead = " +" if ([string]::IsNullOrWhiteSpace($right)) { $rightLineLead = "" } } else { # This is not a difference line, print it "normally" $diffLeftColor = $PSStyle.Reset $diffRightColor = $PSStyle.Reset $leftLineLead = " " $rightLineLead = " " } $lineNumberLeft = "$($line.LeftLineNumber)".PadLeft(5) $lineNumberRight = "$($line.RightLineNumber)".PadLeft(5) $right = "$rightLineLead$right".PadRight($fixedWidth," ").Substring(0,$fixedWidth) $left = "$leftLineLead$left".PadRight($fixedWidth," ").Substring(0,$fixedWidth) $print += "$lineNumberColor$lineNumberLeft$reset $diffLeftColor$left$reset :$lineNumberColor$lineNumberRight$reset $diffRightColor$right$reset" $printedLineNumbers += $i } if ($groupCounter -lt $groupsCount) { if ($last -lt ($groups[$groupCounter][0] - $SurroundingLines)) { $print += Show-Line -Style LeftHalf } } $groupCounter += 1 } if ($print.Count -gt 0) { $print } else { } } else { if (!$Porcelain) { "$fileHeaderPrint $fileHeaderFrom : $fileHeaderTo" Write-Host "Contents were the same" } return } <# $lineNumber = 0 $fromResults = @{} $toResults = @{} $lineNumbers = @() foreach ($line in $comparedLines) { $lineNumber = $line.InputObject.ReadCount if($line.SideIndicator -eq "=>") { $lineNumbers += $lineNumber $lineOperation = "added" $fromResults[$lineNumber] = $line.InputObject } elseif($line.SideIndicator -eq "<=") { $lineNumbers += $lineNumber $lineOperation = "deleted" $toResults[$lineNumber] = $line.InputObject } } if ($lineNumbers.Count -gt 0) {} $lineNumbers = $lineNumbers | Sort-Object | Get-Unique $print = @() foreach ($lineNumber in $lineNumbers) { $lineNumberLead = "$lineNumber".PadLeft(5, ' ') $from = $fromResults[$lineNumber] $from = "$from".PadRight($fixedWidth," ").Substring(0,$fixedWidth) $to = $toResults[$lineNumber] $to = "$to".PadRight($fixedWidth," ").Substring(0,$fixedWidth) $print += "$($PSStyle.ForegroundColor.LightCyan)$lineNumberLead$($PSStyle.Reset) : $($PSStyle.ForegroundColor.LightRed)$from$($PSStyle.Reset) : $($PSStyle.ForegroundColor.Green)$to$($PSStyle.Reset)" } if ($print.Count -gt 0) { "$fileHeaderPrint : $fileHeaderFrom : $fileHeaderTo" $print } else { } #> }