GitHub Icon Image
GitHub

Get and compare documents hash from different tenants

Summary

This script compares files from two different SharePoint tenants by calculating and comparing their hash values. This is useful for verifying file integrity after migrations or ensuring files are identical across tenants. This sample is available in both PnP PowerShell and CLI for Microsoft 365.

Example of script output of the CLI for Microsoft 365 version:

preview CLI for Microsoft 365 output

  • PnP PowerShell
  • CLI for Microsoft 365
# Connect to the first tenant
$Connection1 = Connect-PnPOnline -Url "https://[TenantName1].sharepoint.com/sites/[siteName1]" -Interactive -ReturnConnection
$file1 = Get-PnPFile -Url "/Shared%20Documents/document.docx" -AsMemoryStream -Connection $Connection1

# Connect to the first tenant
$Connection2 = Connect-PnPOnline -Url "https://[TenantName2].sharepoint.com/sites/[siteName2]" -Interactive -ReturnConnection
$file2 = Get-PnPFile -Url "/Shared%20Documents/document.docx" -AsMemoryStream -Connection $Connection2


# Compare the hash of the two files
$hash1 = $(Get-FileHash -InputStream $file1).Hash
$hash2 = $(Get-FileHash -InputStream $file2).Hash

# Output the results of the comparison
if ($hash1 -eq $hash2) {
    Write-Host "The two files have the same hash."
} else {
    Write-Host "The two files have different hashes."
}

Check out the PnP PowerShell to learn more at: https://aka.ms/pnp/powershell

The way you login into PnP PowerShell has changed please read PnP Management Shell EntraID app is deleted : what should I do ?

[CmdletBinding()]
param(
    [Parameter(Mandatory, HelpMessage = "URL of the site in first tenant")]
    [string]$WebUrl1,
    
    [Parameter(Mandatory, HelpMessage = "Server-relative URL of the file in first tenant")]
    [string]$FileUrl1,
    
    [Parameter(Mandatory, HelpMessage = "URL of the site in second tenant")]
    [string]$WebUrl2,
    
    [Parameter(HelpMessage = "Server-relative URL of the file in second tenant (defaults to same as FileUrl1)")]
    [string]$FileUrl2,
    
    [Parameter(HelpMessage = "Name for the first tenant connection (defaults to 'tenant1')")]
    [string]$Connection1Name = "tenant1",
    
    [Parameter(HelpMessage = "Name for the second tenant connection (defaults to 'tenant2')")]
    [string]$Connection2Name = "tenant2"
)

begin {
    if ([string]::IsNullOrEmpty($FileUrl2)) {
        $FileUrl2 = $FileUrl1
    }
    
    Write-Host "Setting up connections to both tenants..." -ForegroundColor Cyan
    
    Write-Host "Logging in to first tenant ($WebUrl1)..." -ForegroundColor Cyan
    m365 login --connectionName $Connection1Name
    if ($LASTEXITCODE -ne 0) {
        throw "Failed to login to first tenant"
    }
    
    Write-Host "Logging in to second tenant ($WebUrl2)..." -ForegroundColor Cyan
    m365 login --connectionName $Connection2Name
    if ($LASTEXITCODE -ne 0) {
        throw "Failed to login to second tenant"
    }
    
    $tempDir = Join-Path $env:TEMP "CompareFiles-$(Get-Date -Format 'yyyyMMddHHmmss')"
    New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
    $tempFile1 = Join-Path $tempDir "file1.tmp"
    $tempFile2 = Join-Path $tempDir "file2.tmp"
}

process {
    try {
        Write-Host "`nSwitching to first tenant connection..." -ForegroundColor Cyan
        m365 connection use --name $Connection1Name | Out-Null
        if ($LASTEXITCODE -ne 0) {
            throw "Failed to switch to first tenant connection"
        }
        
        Write-Host "Downloading file from first tenant: $FileUrl1" -ForegroundColor Cyan
        $result1 = m365 spo file get --webUrl $WebUrl1 --url $FileUrl1 --asFile --path $tempFile1 2>&1
        if ($LASTEXITCODE -ne 0) {
            throw "Failed to download file from first tenant: $result1"
        }
        
        Write-Host "`nSwitching to second tenant connection..." -ForegroundColor Cyan
        m365 connection use --name $Connection2Name | Out-Null
        if ($LASTEXITCODE -ne 0) {
            throw "Failed to switch to second tenant connection"
        }
        
        Write-Host "Downloading file from second tenant: $FileUrl2" -ForegroundColor Cyan
        $result2 = m365 spo file get --webUrl $WebUrl2 --url $FileUrl2 --asFile --path $tempFile2 2>&1
        if ($LASTEXITCODE -ne 0) {
            throw "Failed to download file from second tenant: $result2"
        }
        
        Write-Host "`nCalculating file hashes..." -ForegroundColor Cyan
        $hash1 = (Get-FileHash -Path $tempFile1 -Algorithm SHA256).Hash
        $hash2 = (Get-FileHash -Path $tempFile2 -Algorithm SHA256).Hash
        
        Write-Host "`nComparison Results:" -ForegroundColor White
        Write-Host "==================" -ForegroundColor White
        Write-Host "File 1 ($Connection1Name): $FileUrl1" -ForegroundColor Gray
        Write-Host "Hash 1: $hash1" -ForegroundColor Gray
        Write-Host "`nFile 2 ($Connection2Name): $FileUrl2" -ForegroundColor Gray
        Write-Host "Hash 2: $hash2" -ForegroundColor Gray
        
        Write-Host "`nResult: " -NoNewline
        if ($hash1 -eq $hash2) {
            Write-Host "Files are IDENTICAL" -ForegroundColor Green
        } else {
            Write-Host "Files are DIFFERENT" -ForegroundColor Red
        }
    } finally {
        if (Test-Path $tempDir) {
            Remove-Item -Path $tempDir -Recurse -Force
        }
    }
}

# Example 1: Compare same file across two tenants
# .\Compare-Files.ps1 -WebUrl1 "https://contoso.sharepoint.com/sites/Site1" -FileUrl1 "/Shared Documents/document.docx" -WebUrl2 "https://fabrikam.sharepoint.com/sites/Site2" -Connection1Name "contoso" -Connection2Name "fabrikam"

# Example 2: Compare different file paths
# .\Compare-Files.ps1 -WebUrl1 "https://contoso.sharepoint.com/sites/Site1" -FileUrl1 "/Shared Documents/doc1.pdf" -WebUrl2 "https://fabrikam.sharepoint.com/sites/Site2" -FileUrl2 "/Documents/doc2.pdf"

# Example 3: Compare with default connection names (tenant1, tenant2)
# .\Compare-Files.ps1 -WebUrl1 "https://contoso.sharepoint.com/sites/Site1" -FileUrl1 "/Shared Documents/report.xlsx" -WebUrl2 "https://fabrikam.sharepoint.com/sites/Site2"

Check out the CLI for Microsoft 365 to learn more at: https://aka.ms/cli-m365

Important changes coming to the way you login into CLI for Microsoft 365 (effective 9th September 2024) see Changes in PnP Management Shell registration in Microsoft 365

Contributors

Author(s)
Valeras Narbutas
Adam Wójcik @Adam-it

Disclaimer

THESE SAMPLES ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.

Back to top Script Samples
Generated by DocFX with Material UI