SharePoint Online: Migrate a Folder with Sub-Folders and Files to SharePoint Online using PowerShell

Requirement: Migrate a folder with its sub-folders and files to SharePoint Online using PowerShell.

SharePoint Online Migrate a Folder to SharePoint Online using PowerShell

PowerShell to copy a Folder with Its Sub-Folders and Files to SharePoint Online:

Here is the PnP PowerShell to copy all files and sub-folders from a given folder from a local drive (or network drive) to SharePoint Online.  

#Function to Copy Multiple Files with Folder structure to SharePoint Online Document Library
Function Migrate-PnPFolderToSPO()
{
    param
    (
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $SourceFolderPath,
        [Parameter(Mandatory=$true)] [string] $LibraryName,
        [Parameter(Mandatory=$true)] [string] $LogFile
    )
 
    Try {
        Add-content $Logfile -value "`n---------------------- File Upload Script Started: $(Get-date -format 'dd/MM/yyy hh:mm:ss tt')-------------------"
     
        #Connect to PnP Online
        Connect-PnPOnline -Url $SiteURL -UseWebLogin  

        #Get the Target Folder to Upload
        $Web = Get-PnPWeb
        $List = Get-PnPList $LibraryName -Includes RootFolder
        $TargetFolder = $List.RootFolder
        $TargetFolderSiteRelativeURL = $TargetFolder.ServerRelativeURL.Replace($Web.ServerRelativeUrl,[string]::Empty)
 
        #Get All Items from the Source
        $Source = Get-ChildItem -Path $SourceFolderPath -Recurse
        $SourceItems = $Source | Select FullName, PSIsContainer, @{Label='TargetItemURL';Expression={$_.FullName.Replace($SourceFolderPath,$TargetFolderSiteRelativeURL).Replace("\","/")}}
        Add-content $Logfile -value "Number of Items Found in the Source: $($SourceItems.Count)"
 
        #Upload Source Items from Fileshare to Target SharePoint Online document library
        $Counter = 1
        $SourceItems | ForEach-Object {
                #Calculate Target Folder URL
                $TargetFolderURL = (Split-Path $_.TargetItemURL -Parent).Replace("\","/")
                $ItemName = Split-Path $_.FullName -leaf
                   
                #Replace Invalid Characters
                $ItemName = [RegEx]::Replace($ItemName, "[{0}]" -f ([RegEx]::Escape([String]'\*:<>?/\|')), '_')

                #Display Progress bar
                $Status  = "uploading '" + $ItemName + "' to " + $TargetFolderURL +" ($($Counter) of $($SourceItems.Count))"
                Write-Progress -Activity "Uploading ..." -Status $Status -PercentComplete (($Counter / $SourceItems.Count) * 100)
 
                If($_.PSIsContainer)
                {
                    #Ensure Folder
                    $Folder  = Resolve-PnPFolder -SiteRelativePath ($TargetFolderURL+"/"+$ItemName)
                    Write-host "Ensured Folder '$($ItemName)' to Folder $TargetFolderURL"
                    Add-content $Logfile -value "Ensured Folder '$($ItemName)' to Folder $TargetFolderURL"
                }
                Else
                {
                        #Upload File
                        $File  = Add-PnPFile -Path $_.FullName -Folder $TargetFolderURL
                        Write-host "Uploaded File '$($_.FullName)' to Folder $TargetFolderURL"
                        Add-content $Logfile -value "Uploaded File '$($_.FullName)' to Folder $TargetFolderURL"                        
                }
                $Counter++
        }
}
    Catch {
        Write-host -f Red "Error:" $_.Exception.Message
        Add-content $Logfile -value "Error:$($_.Exception.Message)"
    }
    Finally {
       Add-content $Logfile -value "---------------------- File upload Script Completed: $(Get-date -format 'dd/MM/yyy hh:mm:ss tt')-----------------"
    }
}
 
#Call the Function to Upload a Folder to SharePoint Online
Migrate-PnPFolderToSPO -SiteURL "https://crescent.sharepoint.com/sites/marketing" -SourceFolderPath "C:\Documents" -LibraryName "Migration" -LogFile "C:\Temp\Migration-LOG.log"

This script copies the contents of a folder to the SharePoint Online document library. It overwrites any existing file in the target SharePoint Online library. It creates folder if it doesn’t exist on the target site already.We can also use this script to migrate files and folders from network file share to SharePoint Online document library!

Salaudeen Rajack

Salaudeen Rajack is a SharePoint Architect with Two decades of SharePoint Experience. He loves sharing his knowledge and experiences with the SharePoint community, through his real-world articles!

9 thoughts on “SharePoint Online: Migrate a Folder with Sub-Folders and Files to SharePoint Online using PowerShell

  • December 23, 2020 at 9:42 AM

    no bigger than 250MB..

    Reply
  • December 7, 2020 at 10:35 AM

    i read that “It overwrites any existing file in the target SharePoint Online library”
    how can we check if a file/files already exist then it can move forward to next upload! like an incremental procedure?

    Reply
    • December 8, 2020 at 11:32 AM

      Use:
      $FileExists = Get-PnPFile -Url $FileServerRelativeURL -ErrorAction SilentlyContinue
      If(!$FileExists)
      {
      #Upload File
      }

      Reply
  • October 27, 2020 at 6:00 PM

    This was very helpful for me. Many thanks!

    Reply
  • September 7, 2020 at 9:49 PM

    hey great script ive been working on modifying this slightly i am trying to use this to move copy everything in a D: to a sharepoint site but when i change the -SourceFolderPath to D:* its throwing an error Add-PnPFile : Access denied. You do not have permission to perform this action or access this resource. but when i say do somthing like -sourcefolderpath D:Test it copys the contents fine any ideas what im doing wrong

    Reply
    • September 8, 2020 at 9:11 AM

      That’s the default behavior! If you try to create any file in root of the drive, you’ll get access denied even from GUI. However, If you run the script as Administrator, you won’t face this issue.

      Reply
  • March 19, 2020 at 1:41 PM

    great script! thanks for sharing…

    but, what if i want to copy inside a subfolder(or more levels)..for example inside of “shared documents”

    regards

    Reply
    • March 19, 2020 at 4:29 PM

      nevermind….solved by adding:
      $TargetFolderSiteRelativeURL = $TargetFolderSiteRelativeURL + “/TEST”

      Reply
  • March 19, 2020 at 1:39 PM

    hello

    great script! really…but, what if i want to copy to subfolders in “shared documents”……eg “shared fodersTEST”

    regards

    Reply

Leave a Reply