Public/Convert-FSMSharePath.ps1
|
function Convert-FSMSharePath { <# .SYNOPSIS Produces a new share-inventory CSV with paths remapped from an old root to a new root. .DESCRIPTION Reads an exported share CSV and rewrites the start of each Path that begins with -OldRoot so it begins with -NewRoot instead. For example D:\Shares\HR becomes E:\Data\HR when OldRoot is 'D:\Shares' and NewRoot is 'E:\Data'. Matching is case-insensitive (correct for Windows paths). Any path that does NOT start with OldRoot is left unchanged and reported as a warning, so you can spot shares that would otherwise be recreated on the wrong drive. .PARAMETER InputPath The source share CSV (from Export-FSMShareInventory). .PARAMETER OutputPath Where to write the remapped CSV. .PARAMETER OldRoot The path prefix to replace, e.g. 'D:\Shares'. .PARAMETER NewRoot The replacement prefix, e.g. 'E:\Data'. .EXAMPLE Convert-FSMSharePath -InputPath C:\Temp\shares.csv -OutputPath C:\Temp\remapped.csv -OldRoot 'D:\Shares' -NewRoot 'E:\Data' #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '', Justification = 'The MatchEvaluator delegate signature requires a match parameter; replacement is a constant new root, so the match itself is intentionally unused.')] [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$InputPath, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$OutputPath, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$OldRoot, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$NewRoot ) if (-not (Test-Path -Path $InputPath)) { throw "Input CSV not found: '$InputPath'." } $shares = @(Import-Csv -Path $InputPath) Assert-FSMCsvColumn -InputObject $shares -RequiredColumn 'Path' -Path $InputPath $escapedOldRoot = [regex]::Escape($OldRoot.TrimEnd('\')) $newRootClean = $NewRoot.TrimEnd('\') $pattern = "^$escapedOldRoot" $unmatched = 0 foreach ($share in $shares) { $original = "$($share.Path)" # Delegate replacement avoids any $-substitution issues if NewRoot contains '$'. $updated = [regex]::Replace( $original, $pattern, { param($m) $newRootClean }, [Text.RegularExpressions.RegexOptions]::IgnoreCase ) if ($updated -eq $original) { $unmatched++ $name = if ($share.PSObject.Properties.Name -contains 'Name') { $share.Name } else { '<unknown>' } Write-FSMStatus -Message "Path not remapped (does not start with '$OldRoot'): share '$name' -> $original" -Level Warning } $share.Path = $updated } $folder = Split-Path -Path $OutputPath -Parent if ($folder -and -not (Test-Path -Path $folder)) { New-Item -Path $folder -ItemType Directory -Force | Out-Null } $shares | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8 $remapped = $shares.Count - $unmatched Write-FSMStatus -Message "Remapped $remapped of $($shares.Count) path(s) -> $OutputPath ($unmatched left unchanged)" -Level Success return $shares } |