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()
        [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,"")
        #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)
                    #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"
                        #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"                        
    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 "" -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!


  1. hello

    great script! really...but, what if i want to copy to subfolders in "shared documents" "shared foders\TEST"


  2. great script! thanks for sharing...

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


    1. nevermind....solved by adding:
      $TargetFolderSiteRelativeURL = $TargetFolderSiteRelativeURL + "/TEST"

  3. 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

    1. 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.

  4. This was very helpful for me. Many thanks!

  5. 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?

    1. Use:
      $FileExists = Get-PnPFile -Url $FileServerRelativeURL -ErrorAction SilentlyContinue
      #Upload File


Please Login and comment to get your questions answered!

Powered by Blogger.