- Current state: 3,249/3,768 files uploaded, 519 remaining - Active RMM command: 9e0fcfe8 (running on ACG-DWP-X-BB) - Working upload script with drive ID concatenation fix - Comprehensive continuation instructions - All verification scripts Client very angry - this was promised yesterday Issue: PowerShell escaping ! in drive ID (b! -> b\!) Solution: String concatenation at runtime
110 lines
3.6 KiB
PowerShell
110 lines
3.6 KiB
PowerShell
# Mirror Datto Quality Department to SharePoint via OneDrive sync
|
|
# Uses robocopy /MIR to make destination EXACTLY match source
|
|
# Deletes files in SharePoint that don't exist in Datto
|
|
|
|
param(
|
|
[switch]$Confirm,
|
|
[switch]$DryRun
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$DattoSource = "C:\Users\Public\Desktop\Datto Workplace Server Projects\Quality Department"
|
|
$SharePointDest = "C:\Users\Administrator\OneDrive - Birth Biologic, LLC\Quality Systems Department\Documents"
|
|
|
|
Write-Host "[INFO] Starting mirror from Datto to SharePoint via OneDrive sync..."
|
|
Write-Host "[INFO] Source (Datto): $DattoSource"
|
|
Write-Host "[INFO] Destination (SharePoint/OneDrive): $SharePointDest"
|
|
Write-Host ""
|
|
|
|
# Verify paths exist
|
|
if (-not (Test-Path $DattoSource)) {
|
|
throw "Source path does not exist: $DattoSource"
|
|
}
|
|
|
|
if (-not (Test-Path $SharePointDest)) {
|
|
throw "Destination path does not exist: $SharePointDest"
|
|
}
|
|
|
|
# Get file counts before
|
|
$beforeCount = (Get-ChildItem $SharePointDest -Recurse -File -ErrorAction SilentlyContinue | Measure-Object).Count
|
|
Write-Host "[INFO] Files in SharePoint before: $beforeCount"
|
|
Write-Host ""
|
|
|
|
# Show what robocopy will do (dry run)
|
|
Write-Host "[DRY RUN] Simulating robocopy /MIR (mirror)..."
|
|
Write-Host ""
|
|
|
|
$dryRunLog = "C:\temp\robocopy-quality-dryrun.log"
|
|
New-Item -Path "C:\temp" -ItemType Directory -Force | Out-Null
|
|
|
|
robocopy $DattoSource $SharePointDest /MIR /L /NP /NDL /NFL /LOG:$dryRunLog /R:0 /W:0
|
|
|
|
# Parse dry run log to show what will be deleted
|
|
$logContent = Get-Content $dryRunLog -Raw
|
|
if ($logContent -match '\*EXTRA File\s+(.+)') {
|
|
Write-Host "[WARNING] Files that will be DELETED from SharePoint (not in Datto):"
|
|
Write-Host ""
|
|
Get-Content $dryRunLog | Where-Object { $_ -match '\*EXTRA File' } | ForEach-Object {
|
|
if ($_ -match '\*EXTRA File\s+\d+\s+(.+)') {
|
|
Write-Host " - $($Matches[1])"
|
|
}
|
|
}
|
|
Write-Host ""
|
|
}
|
|
|
|
# Count files to be deleted
|
|
$extraFiles = (Get-Content $dryRunLog | Where-Object { $_ -match '\*EXTRA File' }).Count
|
|
Write-Host "[INFO] $extraFiles file(s) will be deleted"
|
|
Write-Host ""
|
|
|
|
# Exit after dry run if -DryRun specified
|
|
if ($DryRun) {
|
|
Write-Host "[DRY RUN ONLY] Use -Confirm to execute actual mirror"
|
|
exit 0
|
|
}
|
|
|
|
# Confirm before proceeding
|
|
if (-not $Confirm) {
|
|
$response = Read-Host "Proceed with ACTUAL mirror? This will DELETE $extraFiles files from SharePoint. Type 'yes' to confirm"
|
|
|
|
if ($response -ne 'yes') {
|
|
Write-Host "[CANCELLED] No changes made"
|
|
exit 1
|
|
}
|
|
} else {
|
|
Write-Host "[INFO] Running with -Confirm switch, proceeding automatically..."
|
|
}
|
|
|
|
# Execute actual mirror
|
|
Write-Host ""
|
|
Write-Host "[INFO] Executing robocopy /MIR..."
|
|
Write-Host ""
|
|
|
|
$actualLog = "C:\temp\robocopy-quality-actual.log"
|
|
|
|
# /MIR = mirror (copy + purge extra files)
|
|
# /R:0 = no retries on failed copies
|
|
# /W:0 = no wait between retries
|
|
# /MT:8 = use 8 threads
|
|
# /LOG = write log file
|
|
robocopy $DattoSource $SharePointDest /MIR /R:0 /W:0 /MT:8 /LOG:$actualLog /NP
|
|
|
|
$exitCode = $LASTEXITCODE
|
|
|
|
# Robocopy exit codes: 0-7 are success/warnings, 8+ are errors
|
|
if ($exitCode -ge 8) {
|
|
throw "Robocopy failed with exit code $exitCode - check $actualLog"
|
|
}
|
|
|
|
# Get file counts after
|
|
$afterCount = (Get-ChildItem $SharePointDest -Recurse -File -ErrorAction SilentlyContinue | Measure-Object).Count
|
|
Write-Host ""
|
|
Write-Host "[OK] Mirror complete"
|
|
Write-Host "[INFO] Files in SharePoint after: $afterCount (was $beforeCount)"
|
|
Write-Host "[INFO] Files deleted: $($beforeCount - $afterCount)"
|
|
Write-Host "[INFO] Full log: $actualLog"
|
|
Write-Host ""
|
|
Write-Host "[INFO] OneDrive will now sync these changes to SharePoint..."
|
|
Write-Host ""
|