There are several ways to move data between libraries in SharePoint.
One of them is using UI. While this method has become better over the years, it’s still slow and buggy at times. Just recently I had an issue where SharePoint UI would not move more than 20 folders, it would time out.
Another method is using PowerShell to do such a task. Out there you can definitely find scripts that would move data; however, you need to provide all prerequisite information and do it correctly. A typo or a library display name vs different internal name would leave you scratching your head for quite some time. If you do use subsites in your site collections, then things become progressively more complicated.
To address most of the struggle I decided to create a script that will do it all. The goal was to automate everything where an admin would only need to select a location by selecting options. In a nutshell, this is how it can move data from Library A to Library B:
- Everything from Library A to Library B
- Everything from Library A to Folder in Library B
- Folder and its content from Library A to Library B
- Folder and its content from Library A to Folder in Library B
- Content of the folder from Library A to Library B
- Content of the folder from Library A to Folder in Library B
All these options above should cover pretty much every scenario you can possibly have.
Pros:
- The script is streamlined, so it’s hard to make any mistake or select wrong location.
- When selecting a folder, the script checks if it exists.
- Works with site collections and subsites.
Cons:
- When moving data between subsites and site collections, the Modified value will be refreshed
- The script does not move files unless they are within the folder(s) that are being moved.
#---------------------------------------------------[Variables]--------------------------------------------------- $AdminSiteUrl = "https://contoso-admin.sharepoint.com/" $Exclusions = @( "https://contoso.sharepoint.com/portals/hub", "https://contoso-my.sharepoint.com/", "https://contoso.sharepoint.com/portals/Community", "https://contoso.sharepoint.com/search", "https://contoso.sharepoint.com/portals/contoso-Internal-Communications" ) #---------------------------------------------------[Function 1]-------------------------------------------------- Function Get-CollectionType { Begin{} Process{ # Site Collection types $Type = @() $Item1 = new-object PSObject -Property @{Number = 1; Type = 'Site collection'; Value = @('STS#0','EHS#1')} $Item2 = new-object PSObject -Property @{Number = 2; Type = 'Office 365 group'; Value = @('GROUP#0')} $Item3 = new-object PSObject -Property @{Number = 3; Type = 'Project Online'; Value = @('PWA#0')} $Type += $Item1,$Item2,$Item3 $Type | ft Number,Type | Out-Host # Choose Site Collection type Do { Try { $Num = $true [int]$SelectedInput = Read-host "Select SharePoint site collection type by typing its number" } Catch {$Num = $false} } Until (($SelectedInput -gt 0 -and $SelectedInput -le $Type.count) -and $Num -eq $true) $SelectedType = $Type[[int]$SelectedInput - 1].Value $SelectedType } End{} } #---------------------------------------------------[Function 2]-------------------------------------------------- Function Get-SiteCollection { param ( [Parameter(Mandatory=$True)]$SelectedType ) Begin{} Process{ # Get all Site Collections filtered by the choice above $SiteCollections = Get-SPOSite | Where-Object {($Exclusions -cnotcontains $_.Url) -and ($SelectedType -contains $_.Template)} | ForEach -Begin { $i = 1 } -Process { Add-Member -InputObject $_ -MemberType NoteProperty -Name Number -Value ($i++) -PassThru -Force } $SiteCollections | ft Number,Url | Out-Host # Choose Site Collection Do { Try { $Num = $true [int]$SelectedInput = Read-host "Select SharePoint site collection by typing its number" } Catch {$Num = $false} } Until (($SelectedInput -gt 0 -and $SelectedInput -le $SiteCollections.count) -and $Num -eq $true) $SelectedSiteCollection = $SiteCollections[[int]$SelectedInput - 1].Url $SelectedSiteCollection } End{} } #---------------------------------------------------[Function 3]-------------------------------------------------- Function Get-SiteType { Begin{} Process{ # Site types $ChoiceBetweenMainAndSubsites = @() $Item1 = new-object PSObject -Property @{Number = 1; Type = 'Main Site'} $Item2 = new-object PSObject -Property @{Number = 2; Type = 'Subsites'} $ChoiceBetweenMainAndSubsites += $Item1,$Item2 $ChoiceBetweenMainAndSubsites | ft Number,Type | Out-Host # Choose Site type Do { Try { $Num = $true [int]$SelectedInput = Read-host "Choose between a Main site or Subsites by typing the number" } Catch {$Num = $false} } Until (($SelectedInput -gt 0 -and $SelectedInput -le $ChoiceBetweenMainAndSubsites.count) -and $Num -eq $true) $SelectedSiteType = $ChoiceBetweenMainAndSubsites[[int]$SelectedInput - 1].Type $SelectedSiteType } End{} } #---------------------------------------------------[Function 4]-------------------------------------------------- Function Get-SiteAndLibrary { param ( [Parameter(Mandatory=$True)]$SelectedSiteType ) Begin{} Process{ If ($SelectedSiteType -eq 'Main Site') { # List libraries $Libraries = Get-PnPLIst | Where-Object {$_.BaseType -eq "DocumentLibrary"} | ForEach -Begin { $i = 1 } -Process { Add-Member -InputObject $_ -MemberType NoteProperty -Name Number -Value ($i++) -PassThru -Force } $SelectedSubsite = $null $Libraries | ft Number,Title | Out-Host } ElseIf ($SelectedSiteType -eq 'Subsites') { # Get all Subsites $Subsites = Get-PnPSubWebs -Recurse | ForEach -Begin { $i = 1 } -Process { Add-Member -InputObject $_ -MemberType NoteProperty -Name Number -Value ($i++) -PassThru -Force } $Subsites | ft Number,ServerRelativeUrl | Out-Host # Exit if no subsites found If ($Subsites.Count -eq 0) { Write-host `n"No subsites found, exiting the script" -ForegroundColor Red Exit } # Choose Subsite Do { Try { $Num = $true [int]$SelectedInput = Read-host "Select subsite by typing its number" } Catch {$Num = $false} } Until (($SelectedInput -gt 0 -and $SelectedInput -le $Subsites.count) -and $Num -eq $true) $SelectedSubsite = $Subsites[[int]$SelectedInput - 1].ServerRelativeUrl # List libraries $Libraries = Get-PnPLIst -Web $SelectedSubsite | Where-Object {$_.BaseType -eq "DocumentLibrary"} | ForEach -Begin { $i = 1 } -Process { Add-Member -InputObject $_ -MemberType NoteProperty -Name Number -Value ($i++) -PassThru -Force } $Libraries | ForEach -Process { Add-Member -InputObject $_ -MemberType NoteProperty -Name Url -Value ($_.RootFolder.ServerRelativeUrl.Substring(1)) } $Libraries | ft Number,Title,Url | Out-Host } # Exit if no libraries found If ($Libraries.Count -eq 0) { Write-host `n"No libraries found, exiting the script" -ForegroundColor Red Exit } # Choose Library Do { Try { $Num = $true [int]$SelectedInput = Read-host "Choose a library by typing the number" } Catch {$Num = $false} } Until (($SelectedInput -gt 0 -and $SelectedInput -le $Libraries.count) -and $Num -eq $true) $SelectedLibrary = ($Libraries[[int]$SelectedInput - 1].RootFolder.ServerRelativeUrl).TrimStart("/") If ($SelectedSiteType -eq 'Subsites') { $SelectedLibrary -match $SelectedSubsite.TrimStart("/")+"/(?<LibName>.*)" $SelectedLibrary = $Matches['LibName'] } $SiteAndLibraryObject = new-object PSObject -Property @{Site = $SelectedSubsite; Library = $SelectedLibrary} $SiteAndLibraryObject } End{} } #---------------------------------------------------[Function 5]-------------------------------------------------- Function Get-MoveActionType { Begin{} Process{ # Move action types $Type = @() $Item1 = new-object PSObject -Property @{Number = 1; Move = 'Everything from Library A'; ValueFrom = 'MoveFrom1'; To = "Library B"; ValueTo = 'MoveTo1'} $Item2 = new-object PSObject -Property @{Number = 2; Move = 'Everything from Library A'; ValueFrom = 'MoveFrom1'; To = "Folder in Library B"; ValueTo = 'MoveTo2'} $Item3 = new-object PSObject -Property @{Number = 3; Move = 'Folder and its content from Library A'; ValueFrom = 'MoveFrom2'; To = "Library B"; ValueTo = 'MoveTo1'} $Item4 = new-object PSObject -Property @{Number = 4; Move = 'Folder and its content from Library A'; ValueFrom = 'MoveFrom2'; To = "Folder in Library B"; ValueTo = 'MoveTo2'} $Item5 = new-object PSObject -Property @{Number = 5; Move = 'Content of the folder from Library A'; ValueFrom = 'MoveFrom3'; To = "Library B"; ValueTo = 'MoveTo1'} $Item6 = new-object PSObject -Property @{Number = 6; Move = 'Content of the folder from Library A'; ValueFrom = 'MoveFrom3'; To = "Folder in Library B"; ValueTo = 'MoveTo2'} $Type += $Item1,$Item2,$Item3,$Item4,$Item5,$Item6 $Type | ft Number,Move,To | Out-Host # Choose Move action type Do { Try { $Num = $true [int]$SelectedInput = Read-host "Select move action by typing its number" } Catch {$Num = $false} } Until (($SelectedInput -gt 0 -and $SelectedInput -le $Type.count) -and $Num -eq $true) $SelectedMoveType = $Type[[int]$SelectedInput - 1].Value $SelectedMoveType = new-object PSObject -Property @{ActionFrom = $Type[[int]$SelectedInput - 1].ValueFrom; ActionTo = $Type[[int]$SelectedInput - 1].ValueTo} $SelectedMoveType } End{} } #---------------------------------------------------[Function 6]-------------------------------------------------- Function Move-Folder { param ( [Parameter(Mandatory=$True)]$AdminSiteUrl, [Parameter(Mandatory=$True)]$FolderSourceUrl, [Parameter(Mandatory=$True)]$FolderTargetUrl ) Begin {} Process { Try{ # Setup the context $Context = New-Object Microsoft.SharePoint.Client.ClientContext($AdminSiteURL) $Context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserCredential.Username, $UserCredential.Password) # Move the Folder $MoveCopyOpt = New-Object Microsoft.SharePoint.Client.MoveCopyOptions [Microsoft.SharePoint.Client.MoveCopyUtil]::MoveFolder($Context, $FolderSourceURL, $FolderTargetURL, $MoveCopyOpt) $Context.ExecuteQuery() Write-host "Successfully moved -" $FolderTargetURL -ForegroundColor Green } Catch { write-host "Not moved -" $_.Exception.Message -ForegroundColor Red } } End {} } #---------------------------------------------------[Function 7]-------------------------------------------------- Function Check-Folder { [CmdletBinding(DefaultParameterSetName="MainSiteSet")] param ( [Parameter(ParameterSetName="MainSiteSet", Mandatory=$True)] $Title, [Parameter(ParameterSetName="SubsiteSet", Mandatory=$True)] $SubsiteUrl, [Parameter(ParameterSetName="SubsiteSet", Mandatory=$True)] $SubsiteTitle ) Begin {} Process { Do { Try { $FolderName = Read-host `n"Provide the path of the folder" $FolderName = $FolderName.TrimEnd("/").TrimStart("/") If ($PSCmdlet.ParameterSetName -eq "MainSiteSet") { $GetFolder = Get-PnPFolder -Url ($Title + "/" + $FolderName) -ErrorAction Stop } ElseIf ($PSCmdlet.ParameterSetName -eq "SubsiteSet") { $GetFolder = Get-PnPFolder -Web $SubsiteUrl -Url ($SubsiteTitle + "/" + $FolderName) -ErrorAction Stop } } Catch { Write-Host `n"Cannot find the folder!" -ForegroundColor Red } } Until ($GetFolder -ne $null) Write-Host `n"Found the folder!"`n -ForegroundColor Green $SelectedFolder = new-object PSObject -Property @{FolderPath = $FolderName; FolderName = $GetFolder.Name} $SelectedFolder } End {} } #-----------------------------------------------------[Script]---------------------------------------------------- # Start timer $elapsed = [System.Diagnostics.Stopwatch]::StartNew() # Connect to SharePoint Online Admin Connect-PnPOnline -Url $AdminSiteUrl -Credentials $UserCredential Write-host `n"Select a Move action by typing its number:" -ForegroundColor Green # Call Function 5 $SelectedMoveActionType = Get-MoveActionType Write-host `n"The following questionairy applies to a Source Location:" -ForegroundColor Yellow # Call Function 1 (From) $SelectedTypeFrom = Get-CollectionType # Call Function 2 (From) $SelectedSiteCollectionFrom = Get-SiteCollection -SelectedType $SelectedTypeFrom If ($SelectedSiteCollectionFrom -match '\/$') { $SelectedSiteCollectionFrom = $SelectedSiteCollectionFrom.TrimEnd("/") } # Connect to Site Collection (From) Connect-PnPOnline -Url $SelectedSiteCollectionFrom -Credentials $UserCredential # Call Function 3 (From) $SelectedSiteTypeFrom = Get-SiteType # Call Function 4 (From) $SelectedLibraryFrom = Get-SiteAndLibrary -SelectedSiteType $SelectedSiteTypeFrom # Check if subsite is null and/or remove "/" from the beginning of subsite If ($SelectedLibraryFrom.Site -ne $null) { If ($SelectedLibraryFrom.Site -match '^\/') { $SelectedSubsiteFrom = $SelectedLibraryFrom.Site.Substring(1) } Else { $SelectedSubsiteFrom = $SelectedLibraryFrom.Site } } Else { $SelectedSubsiteFrom = $SelectedLibraryFrom.Site } # Ask for "From" folder if selected move type requires it If ($SelectedMoveActionType.ActionFrom -ne 'MoveFrom1') { If ($SelectedSubsiteFrom -ne $null) { $FolderFrom = Check-Folder -SubsiteUrl $SelectedSubsiteFrom -SubsiteTitle $SelectedLibraryFrom.Library } ElseIf ($SelectedSubsiteFrom -eq $null) { $FolderFrom = Check-Folder -Title $SelectedLibraryFrom.Library } } Write-host "The following questionairy applies to a Target Location:" -ForegroundColor Cyan # Call Function 1 (To) $SelectedTypeTo = Get-CollectionType # Call Function 2 (To) $SelectedSiteCollectionTo = Get-SiteCollection -SelectedType $SelectedTypeTo If ($SelectedSiteCollectionTo -match '\/$') { $SelectedSiteCollectionTo = $SelectedSiteCollectionTo.TrimEnd("/") } # Connect to Site Collection (To) Connect-PnPOnline -Url $SelectedSiteCollectionTo -Credentials $UserCredential # Call Function 3 (To) $SelectedSiteTypeTo = Get-SiteType # Call Function 4 (To) $SelectedLibraryTo = Get-SiteAndLibrary -SelectedSiteType $SelectedSiteTypeTo # Check if subsite is null and/or remove "/" from the beginning of subsite If ($SelectedLibraryTo.Site -ne $null) { If ($SelectedLibraryTo.Site -match '^\/') { $SelectedSubsiteTo = $SelectedLibraryTo.Site.Substring(1) } Else { $SelectedSubsiteTo = $SelectedLibraryTo.Site } } Else { $SelectedSubsiteTo = $SelectedLibraryTo.Site } # Ask for "To" folder if selected move type requires it If ($SelectedMoveActionType.ActionTo -eq 'MoveTo2') { If ($SelectedSubsiteTo -ne $null) { $FolderTo = Check-Folder -SubsiteUrl $SelectedSubsiteTo -SubsiteTitle $SelectedLibraryTo.Library } ElseIf ($SelectedSubsiteTo -eq $null) { $FolderTo = Check-Folder -Title $SelectedLibraryTo.Library } } # Connect to Site Collection (From) Connect-PnPOnline -Url $SelectedSiteCollectionFrom -Credentials $UserCredential # When "From" is main site and "To" is main site If (($SelectedSubsiteFrom -eq $null) -and ($SelectedSubsiteTo -eq $null)) { # Move Option 1 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom1') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo1')) { $Folders = Get-PnPFolderItem -FolderSiteRelativeUrl $SelectedLibraryFrom.Library -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedLibraryFrom.Library + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedLibraryTo.Library + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } # Move Option 2 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom1') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo2')) { $Folders = Get-PnPFolderItem -FolderSiteRelativeUrl $SelectedLibraryFrom.Library -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedLibraryFrom.Library + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderTo.FolderPath + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } # Move Option 3 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom2') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo1')) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderFrom.FolderName Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } # Move Option 4 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom2') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo2')) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderTo.FolderPath + "/" + $FolderFrom.FolderName Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } # Move Option 5 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom3') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo1')) { $Folders = Get-PnPFolderItem -FolderSiteRelativeUrl ($SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath) -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedLibraryTo.Library + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } # Move Option 6 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom3') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo2')) { $Folders = Get-PnPFolderItem -FolderSiteRelativeUrl ($SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath) -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderTo.FolderPath + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } } # When "From" is main site and "To" is subsite ElseIf (($SelectedSubsiteFrom -eq $null) -and ($SelectedSubsiteTo -ne $null)) { # Move Option 1 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom1') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo1')) { $Folders = Get-PnPFolderItem -FolderSiteRelativeUrl $SelectedLibraryFrom.Library -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedLibraryFrom.Library + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedSubsiteTo + "/" + $SelectedLibraryTo.Library + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } # Move Option 2 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom1') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo2')) { $Folders = Get-PnPFolderItem -FolderSiteRelativeUrl $SelectedLibraryFrom.Library -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedLibraryFrom.Library + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedSubsiteTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderTo.FolderPath + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } # Move Option 3 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom2') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo1')) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedSubsiteTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderFrom.FolderName Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } # Move Option 4 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom2') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo2')) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedSubsiteTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderTo.FolderPath + "/" + $FolderFrom.FolderName Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } # Move Option 5 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom3') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo1')) { $Folders = Get-PnPFolderItem -FolderSiteRelativeUrl ($SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath) -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedSubsiteFrom + "/" + $SelectedLibraryTo.Library + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } # Move Option 6 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom3') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo2')) { $Folders = Get-PnPFolderItem -FolderSiteRelativeUrl ($SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath) -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedSubsiteTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderTo.FolderPath + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } } # When "From" is subsite and "To" is main site ElseIf (($SelectedSubsiteFrom -ne $null) -and ($SelectedSubsiteTo -eq $null)) { # Move Option 1 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom1') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo1')) { $Folders = Get-PnPFolderItem -Web $SelectedSubsiteFrom -FolderSiteRelativeUrl $SelectedLibraryFrom.Library -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedSubsiteFrom + "/" + $SelectedLibraryFrom.Library + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedLibraryTo.Library + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } # Move Option 2 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom1') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo2')) { $Folders = Get-PnPFolderItem -Web $SelectedSubsiteFrom -FolderSiteRelativeUrl $SelectedLibraryFrom.Library -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedSubsiteFrom + "/" + $SelectedLibraryFrom.Library + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderTo.FolderPath + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } # Move Option 3 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom2') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo1')) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedSubsiteFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderFrom.FolderName Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } # Move Option 4 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom2') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo2')) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedSubsiteFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderTo.FolderPath + "/" + $FolderFrom.FolderName Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } # Move Option 5 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom3') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo1')) { $Folders = Get-PnPFolderItem -Web $SelectedSubsiteFrom -FolderSiteRelativeUrl ($SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath) -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedSubsiteFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedLibraryTo.Library + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } # Move Option 6 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom3') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo2')) { $Folders = Get-PnPFolderItem -Web $SelectedSubsiteFrom -FolderSiteRelativeUrl ($SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath) -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedSubsiteFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderTo.FolderPath + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } } # When "From" is subsite and "To" is subsite ElseIf (($SelectedSubsiteFrom -ne $null) -and ($SelectedSubsiteTo -ne $null)) { # Move Option 1 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom1') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo1')) { $Folders = Get-PnPFolderItem -Web $SelectedSubsiteFrom -FolderSiteRelativeUrl $SelectedLibraryFrom.Library -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedSubsiteFrom + "/" + $SelectedLibraryFrom.Library + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedSubsiteTo + "/" + $SelectedLibraryTo.Library + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } # Move Option 2 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom1') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo2')) { $Folders = Get-PnPFolderItem -Web $SelectedSubsiteFrom -FolderSiteRelativeUrl $SelectedLibraryFrom.Library -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedSubsiteFrom + "/" + $SelectedLibraryFrom.Library + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedSubsiteTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderTo.FolderPath + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } # Move Option 3 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom2') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo1')) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedSubsiteFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedSubsiteTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderFrom.FolderName Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } # Move Option 4 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom2') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo2')) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedSubsiteFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedSubsiteTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderTo.FolderPath + "/" + $FolderFrom.FolderName Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } # Move Option 5 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom3') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo1')) { $Folders = Get-PnPFolderItem -Web $SelectedSubsiteFrom -FolderSiteRelativeUrl ($SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath) -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedSubsiteFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedSubsiteFrom + "/" + $SelectedLibraryTo.Library + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } # Move Option 6 If (($SelectedMoveActionType.ActionFrom -eq 'MoveFrom3') -and ($SelectedMoveActionType.ActionTo -eq 'MoveTo2')) { $Folders = Get-PnPFolderItem -Web $SelectedSubsiteFrom -FolderSiteRelativeUrl ($SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath) -ItemType Folder| Where-Object {$_.Name -ne "Forms" -and $_.Name -ne "Document"} ForEach ($Folder in $Folders) { $FolderSourceURL = $SelectedSiteCollectionFrom + "/" + $SelectedSubsiteFrom + "/" + $SelectedLibraryFrom.Library + "/" + $FolderFrom.FolderPath + "/" + $Folder.Name $FolderTargetURL = $SelectedSiteCollectionTo + "/" + $SelectedSubsiteTo + "/" + $SelectedLibraryTo.Library + "/" + $FolderTo.FolderPath + "/" + $Folder.Name Move-Folder -AdminSiteUrl $AdminSiteUrl -FolderSourceUrl $FolderSourceURL -FolderTargetUrl $FolderTargetURL } } } # End Timer Write-Host "Total Time: $($elapsed.Elapsed.ToString())" # Clear all variables except for Credentials Get-Variable -Exclude $UserCredential | Remove-Variable * -ErrorAction SilentlyContinue
Hi, receiving this error:
Select SharePoint site collection type by typing its number: 1
Get-SPOSite : No connection available. Use Connect-SPOService before running this CmdLet.
At C:\scripts\move_SP.ps1:43 char:28
+ $SiteCollections = Get-SPOSite | Where-Object {($Exclusions – …
+ ~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-SPOSite], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.Online.SharePoint.PowerShell.GetSite
Hi Gavin,
It looks like you are not connected to your SharePoint Admin site.
Please make sure all links are correct for you at the top of the script and try to replace line#305 with this:
Connect-PnPOnline -Url $AdminSiteUrl
Hey there,
What kind of path is it looking for at ‘Provide the path of the folder:’ step? I’ve tried full URL, single folder name with no spaces, a folder name with quotes around it for folder name with spaces – none of them work and all result in ‘Cannot find the folder!’
The folders reside in the default Documents library, so ‘Documents\Folder\Subfolder’ is the path I’m trying to use. Any ideas?
Thanks!
Hello,
Thanks for stopping by. That step uses get-pnpfolder, so the following example should help:
get-pnpfolder -Url “https://contoso.sharepoint.com/sites/IT/Shared Documents/IT Infrastructure”
If you copy a URL from the browser, then “Shared Documents” must be decoded from “Shared%20Documents”.
As far as the rest of the folder names, they are put in as they appear in the UI.