src/Public/SharePoint/Move-SP365Nav.ps1

function Move-SP365Nav {
    <#
    .SYNOPSIS
        Moves SharePoint navigation nodes between navigation locations or sites.
 
    .DESCRIPTION
        Reads the navigation hierarchy from a source location, recreates it in a
        target location, and then clears the source navigation. Existing target
        navigation is cleared by default.
 
        Provide SourceSite and TargetSite for a cross-site move. Set SameSite to
        true to move between navigation locations in the source site.
 
    .PARAMETER SourceSite
        The absolute URL of the SharePoint site from which navigation is read.
 
    .PARAMETER TargetSite
        The absolute URL of the destination SharePoint site. Provide this
        parameter unless SameSite is true.
 
    .PARAMETER SameSite
        Indicates that the source and target navigation locations belong to the
        source site. The command does not establish a separate target connection
        when this value is true.
 
    .PARAMETER ClearTargetNav
        Controls whether existing target navigation nodes are removed before the
        source nodes are added. The default value is true.
 
    .PARAMETER SourceNavigationLocation
        The PnP navigation location from which nodes are read, such as QuickLaunch
        or TopNavigationBar.
 
    .PARAMETER TargetNavigationLocation
        The PnP navigation location to which nodes are added, such as QuickLaunch
        or TopNavigationBar.
 
    .EXAMPLE
        Move-SP365Nav -SourceSite 'https://contoso.sharepoint.com/sites/source' `
            -TargetSite 'https://contoso.sharepoint.com/sites/target' `
            -SourceNavigationLocation QuickLaunch `
            -TargetNavigationLocation QuickLaunch
 
        Moves Quick Launch navigation between two SharePoint sites.
 
    .EXAMPLE
        Move-SP365Nav -SourceSite 'https://contoso.sharepoint.com/sites/operations' `
            -SameSite $true `
            -SourceNavigationLocation QuickLaunch `
            -TargetNavigationLocation TopNavigationBar
 
        Moves Quick Launch nodes to the top navigation in the same site.
 
    .INPUTS
        None.
 
    .OUTPUTS
        None.
 
    .NOTES
        This command clears the source navigation after populating the target.
        Use Copy-SP365Nav to preserve the source navigation.
    #>

    [CmdletBinding()]
    param (
        [parameter(Mandatory = $true)]
        [string]$SourceSite,
        [parameter(Mandatory = $false)]
        [string]$TargetSite,
        [bool]$SameSite = $false,
        [bool]$ClearTargetNav = $true,
        [PnP.Framework.Enums.NavigationType]$SourceNavigationLocation,
        [PnP.Framework.Enums.NavigationType]$TargetNavigationLocation
    ) 
    Begin {
        $isVerbose = $VerbosePreference -ne 'SilentlyContinue'
        Write-Verbose "Starting Copy-SP365Nav function"
        Write-Debug "SourceSite: $SourceSite, TargetSite: $TargetSite, SameSite: $SameSite, ClearTargetNav: $ClearTargetNav, SourceNavigationLocation: $SourceNavigationLocation, TargetNavigationLocation: $TargetNavigationLocation"
        $privatePath = Join-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -ChildPath "private"
        Write-Verbose "Private path set to $privatePath"
        @(Get-ChildItem -Path $privatePath -Recurse -Filter "*.ps1") | ForEach-Object {
            try {
                . $_.FullName
            }
            catch {
                Write-Verbose "Failed to source $($_.FullName): $($_.Exception.Message)"
            
            }
        }
        Test-ForModuleUpdate
        Write-Verbose "Initialization complete"
        if (-not $SourceSite -and -not $TargetSite) {
            throw "At least one of the parameters (`$SourceSite or `$TargetSite) must be provided."
        }
    }
    Process {
        try {
            Connect-SP365 -Url $SourceSite
            Write-Host "Starting to retrieve navigation from source site"
            $siteNav = Get-SiteNav -NavigationNodeLocation $SourceNavigationLocation
            Write-Host "Finished retrieving navigation from source site"
            Write-Host "Total navigation nodes retrieved: $($siteNav.Count)"
            Write-Host ""
            
            if (-not $SameSite) {
                Connect-SP365 -Url $TargetSite
            }
            if ($ClearTargetNav) {
                Clear-SiteNav -Location $TargetNavigationLocation
            }
            Add-SiteNav -newNavNodes $siteNav -Location $TargetNavigationLocation
            Clear-SiteNav -Location $SourceNavigationLocation
        }
        catch {
            Write-Verbose "An error occurred: $($_.Exception.Message)"
        }
    }
}
# SIG # Begin signature block
# MIIHMAYJKoZIhvcNAQcCoIIHITCCBx0CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBmBjStzQ1dxyUo
# 6adZr1uasLWA/i0sFrealO1n04lQjaCCBBwwggQYMIICgKADAgECAhBH6tQY1Crt
# r02dueiKibmNMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGU0zNjUuVG9vbGtp
# dCBDb2RlIFNpZ25pbmcwHhcNMjYwNzE2MTY1NjE0WhcNMjcwNzE2MTcwNjEzWjAk
# MSIwIAYDVQQDDBlNMzY1LlRvb2xraXQgQ29kZSBTaWduaW5nMIIBojANBgkqhkiG
# 9w0BAQEFAAOCAY8AMIIBigKCAYEAxQCBRWJ923yIy73AwGWtFvfBL/dZHvwCBO05
# dJopbkHGcCqifl9R21PXr5OIjcEFv16ObYL23cPwZaNKCiejuiU32MHwidYHU1k5
# AzFpjwW2uwjeA7Hip3cURwoeOH/LzNa/xNTBRiO70M7gunZCm+FixDcPKf66Tvb1
# iM6pbOFmJvzbGjFqKM6mQRofaCPU89SHW5y43HyZNdiWsJTN4TsWj96Rps4fKhh2
# gToexqi0GhLHhLtVQ8ZxMic6w0C9sCWhYBl3kw1OJdaa/MVBdVAXDOIL0HIG8jOa
# l1x67U1LihXEw1hdc3YabhvSYZ5ZXPV1AZ2z6+Qa0EL9XlJWqBkn0rO6sZB1IkOo
# gfeTxVuI6SjhqpW6QrAFFJzb81qd0dDWmmuVka1yoWEic7naZpDfuh3JZPOUilE1
# Wv3qhBDYN5qg1qXeh0RMosR8rMfKjE8CFvsB7LTibom+22in1x16vmIiv9ep5HNc
# eS0hRa/84+vmXQ8R6hN8x+oWbG8NAgMBAAGjRjBEMA4GA1UdDwEB/wQEAwIHgDAT
# BgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUu9RWiOCtUYtlrLgwzVDsor7P
# p88wDQYJKoZIhvcNAQELBQADggGBAKJksJX6tgjdng//9wRM2ztQn8breDnY/Zki
# 8iXrC94sqCYoYg1lT0pVHZq1ZHpdUNh/xQnjP9asbIqgUt0YiCIASCONV2nM2wyK
# VjrvxaC08xefuHiO/R6Uc9sDW38mID+gDoAmswmB9JV5qm+j8b4hw3vcwuUe3nla
# 5bn3YoKXLY4/YJjHNA62TmhYNfs7iwdk2vyH/dCvD35LdBhP/y2ChmOxzI1aSp4L
# c65zCFVDPzw1IED/5q9NM48QUVDgVAX6VNuocjXZpWd7fHf7KFLRJSExXtaYQCdk
# hBSITzd5WBT2opKF02TrTyc5h1zCTr6HU+1Eqr92fvEGfqk4yYSt4plyqbm6Unnq
# gEgwDqlgm9ZNA8hzorcoxSetVVZ8z+50KB55JRTENZ/5kOJWzPtoIA+PdmFvg3wU
# jQHhO6C32rdVUk+j1hI1zL6sR8gYn5VmLPVjfs49yKf+2t3iDsaYVRNawOqHrMZj
# g59c2M2hT5D6krLsI8r3F/t3YfHbKjGCAmowggJmAgEBMDgwJDEiMCAGA1UEAwwZ
# TTM2NS5Ub29sa2l0IENvZGUgU2lnbmluZwIQR+rUGNQq7a9Nnbnoiom5jTANBglg
# hkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3
# DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEV
# MC8GCSqGSIb3DQEJBDEiBCD5lGvvzD1TsBru5/7Sejlt0aNPCRSzedHHerasn7lH
# GzANBgkqhkiG9w0BAQEFAASCAYCz1BgjWXtPxP1OKFZ84vWACTz0BEci6qn1QjVX
# W6gJHkhCOlq1TDhCZrJzGxR4Lzq4pZ5Ta98+VnykKNKapejCa5P/9DU4PF+xtszV
# bcRRuKkbED0EBGmjAu1H1RyBXb2PwjDz4GQCDaRbZlc90onQh/cXILSiybj3+Klt
# I+Ufl3VNZdQyS+Ng7asq5smimqcr3s/JB5AV/tBHDYFF8TnyM5B+6RQN0EZeT4UG
# wPcmg0wEtYPMq4w5QazGmKK52k/HKkxH5htvzK6pIHybJ1u9cmbUHmdExaQpAvcD
# a7+9sytrZVfmw3wSLAho73i804R6RZHLZPMUdKa1oGJ9eUL5cUEa79ahSCXWt5Jk
# +aarrGqf2dLsXl0L/U1MwvbHoulFU9rg6lrUbf4S3C60D5wdhWW5MQ2xm0ap4Xix
# h34N1bZE6lsW6g4uuAzD9iUfviBifpOybDmewI0HM9uR5Egg9phtgp5uWpyIsUyC
# zOQI9+lKCLk/g3NlwOgh13g+LX4=
# SIG # End signature block