SharePoint Online: Copy File Between Document Libraries using PowerShell

Requirement: SharePoint Online PowerShell to copy files from one library to another.

How to Copy a File in SharePoint Online Document Library?

Are you looking for a way to copy files in SharePoint Online? This guide will show you how to use the “Copy to” feature to quickly and easily copy files between your sites, document libraries, or folders. We’ll also show you how to use PowerShell to copy files between locations in your SharePoint Online environment.

You can copy files from one SharePoint Online library to another by using the modern experience. Here is how to copy a file in SharePoint Online Document Library:

  1. Navigate to your SharePoint Online document library that contains the files you want to copy >> Select the files you wish to copy >> Right-click and select the “Copy To” menu item. You can also use the “Copy To” button in the toolbar.sharepoint online copy document
  2. A new window will appear, allowing you to select where you want to copy the files to. Select the target library to which your file needs to be copied. You can choose the current library, any other library on the current site, or even a library in any different site collection. sharepoint online copy file
  3. Pick the library and click on the “Copy Here” button to start copying the file.
  4. You’ll see the “Copying” message in the toolbar, and your file will be copied momentarily on the destination site.
    sharepoint online powershell copy documents

The same procedure applies to move operations as well.

Can’t find your site under Quick Access on the “Copy to” or “Move to” page? Well, you can add your destination library shortcut to OneDrive using “Add Shortcut to OneDrive” and then click on “My Files” in the “Copy to” page to pick that library. Alternatively, You can use the “Add to Quick Access” on your destination library.

Copy VS Move in SharePoint Online
When you copy files, Metadata like created by, modified are not preserved. Also, the Version history is not maintained when the file is copied. Whereas Move preserves the metadata and versions.

Do you often need to copy files from your SharePoint Online environment to other locations? PowerShell can make this process quick and easy!

SharePoint Online: PowerShell to Copy Documents

PowerShell is a powerful tool that you can use to automate tasks in SharePoint Online. Let’s see how to use PowerShell to copy files in SharePoint Online. Here is the PowerShell to copy a file in the SharePoint Online document library:

Function Copy-File
{
  param
    (
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $SourceFileURL,
        [Parameter(Mandatory=$true)] [string] $TargetFileURL
    )
    Try {
        $Cred= Get-Credential
        $Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)
        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = $Credentials
        #Get the source file
        $SourceFile =$Ctx.Web.GetFileByServerRelativeUrl($SourceFileURL)
        $Ctx.Load($SourceFile)
        $Ctx.ExecuteQuery()
        #Copy File to destination
        $SourceFile.CopyTo($TargetFileURL, $True)
        $Ctx.ExecuteQuery()
        Write-Host "File Copied from '$SourceFileURL' to '$TargetFileURL'" -F Green
       }
    Catch {
        write-host -f Red "Error Copying File!" $_.Exception.Message
    }
}
#Set Parameter values
$SiteURL="https://crescent.sharepoint.com/"
$SourceFileURL="/Project Documents/Active Users.xlsx"
$TargetFileURL="/Project Documents/Active UsersV2.xlsx"
#Call the function 
Copy-File -SiteURL $SiteURL -SourceFileURL $SourceFileURL -TargetFileURL $TargetFileURL 

This method copies the given document either to the same document library or a different document library within the same site along with its metadata fields (Except: Created by and Modified by fields – and obviously, the columns should exist in both libraries)!

SharePoint Online: Copy files between site collections using PowerShell

Here is the PowerShell to copy files from one library to another in SharePoint Online:

#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
 
#Function to Copy a File
Function Copy-SPOFile([String]$SiteURL, [String]$SourceFileURL, [String]$TargetFileURL)
{
    Try{
        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)
     
        #Copy the File
        $MoveCopyOpt = New-Object Microsoft.SharePoint.Client.MoveCopyOptions
        $Overwrite = $True
        [Microsoft.SharePoint.Client.MoveCopyUtil]::CopyFile($Ctx, $SourceFileURL, $TargetFileURL, $Overwrite, $MoveCopyOpt)
        $Ctx.ExecuteQuery()
 
        Write-host -f Green "File Copied Successfully!"
    }
    Catch {
    write-host -f Red "Error Copying the File!" $_.Exception.Message
    }
}
 
#Set Config Parameters
$SiteURL="https://Crescent.sharepoint.com/sites/Marketing"
$SourceFileURL="https://Crescent.sharepoint.com/sites/Marketing/Shared Documents/Discloser Asia.doc"
$TargetFileURL="https://Crescent.sharepoint.com/Shared Documents/Discloser Asia.doc"
 
#Get Credentials to connect
$Cred= Get-Credential
 
#Call the function to Copy the File
Copy-SPOFile $SiteURL $SourceFileURL $TargetFileURL

Copy All Files from One Document Library to Another using PowerShell:

This time, let’s copy all files along with their folder-subfolder structure.

#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
Function Copy-AllFiles
{
  param
    (
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [Microsoft.SharePoint.Client.Folder] $SourceFolder,
        [Parameter(Mandatory=$true)] [Microsoft.SharePoint.Client.Folder] $TargetFolder
    )
    Try {
        #Get all Files from the source folder
        $SourceFilesColl = $SourceFolder.Files
        $Ctx.Load($SourceFilesColl)
        $Ctx.ExecuteQuery()
        #Iterate through each file and copy
        Foreach($SourceFile in $SourceFilesColl)
        {
            #Get the source file
            $SourceFile =$Ctx.Web.GetFileByServerRelativeUrl($SourceFile.ServerRelativeUrl)
            $Ctx.Load($SourceFile)
            $Ctx.ExecuteQuery()
            
            #Copy File to destination
            $TargetFileURL = $TargetFolder.ServerRelativeUrl+"/"+$SourceFile.Name
            $SourceFile.CopyTo($TargetFileURL, $True)
            $Ctx.ExecuteQuery()
            Write-host -f Green "Copied File '$($SourceFile.ServerRelativeUrl)' to '$TargetFileURL'"
        }
        #Process Sub Folders
        $SubFolders = $SourceFolder.Folders
        $Ctx.Load($SubFolders)
        $Ctx.ExecuteQuery()
        Foreach($SubFolder in $SubFolders)
        {
            If($SubFolder.Name -ne "Forms")
            {
                #Prepare Target Folder
                $TargetFolderURL = $SubFolder.ServerRelativeUrl -replace $SourceLibrary.RootFolder.ServerRelativeUrl, $TargetLibrary.RootFolder.ServerRelativeUrl
                Try {
                        $Folder=$Ctx.web.GetFolderByServerRelativeUrl($TargetFolderURL)
                        $Ctx.load($Folder)
                        $Ctx.ExecuteQuery()
                    }
                catch {
                        #Create Folder
                        if(!$Folder.Exists)
                        {
                            $Folder=$Ctx.Web.Folders.Add($TargetFolderURL)
                            $Ctx.Load($Folder)
                            $Ctx.ExecuteQuery()
                            Write-host "Folder Added:"$SubFolder.Name -f Yellow
                        }
                    }
                #Call the function recursively
                Copy-AllFiles -SiteURL $SiteURL -SourceFolder $SubFolder -TargetFolder $Folder
            }
        } 
    }
    Catch {
        write-host -f Red "Error Copying File!" $_.Exception.Message
    }
}
#Set Parameter values
$SiteURL="https://crescent.sharepoint.com"
$SourceLibraryName="Project Documents"
$TargetLibraryName="Documents"
#Setup Credentials to connect
$Cred= Get-Credential
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)
#Setup the context
$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$Ctx.Credentials = $Credentials
     
#Get the source library and Target Libraries
$SourceLibrary = $Ctx.Web.Lists.GetByTitle($SourceLibraryName)
$Ctx.Load($SourceLibrary)
$Ctx.Load($SourceLibrary.RootFolder)
$TargetLibrary = $Ctx.Web.Lists.GetByTitle($TargetLibraryName)
$Ctx.Load($TargetLibrary)
$Ctx.Load($TargetLibrary.RootFolder)
$Ctx.ExecuteQuery()
#Call the function 
Copy-AllFiles -SiteURL $SiteURL -SourceFolder $SourceLibrary.RootFolder -TargetFolder $TargetLibrary.RootFolder

PnP PowerShell to Copy a File in SharePoint Online:

Copying a file in the SharePoint Online document library each time can be tedious! Here is how to automate the process of copying files in SharePoint Online using PowerShell.

#Config Variables
$SiteURL = "https://Crescent.sharepoint.com/sites/marketing"
$SourceURL= "Shared Documents/Discloser Asia.doc"
$TargetURL = "Shared Documents/Discloser Asia-v2.doc"

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Credentials (Get-Credential)

#Copy File to same document library
Copy-PnPFile -SourceUrl $SourceURL -TargetUrl $TargetURL -Force

PowerShell to Copy a File Between Folders in SharePoint Online

Here is a PowerShell example for copying a file from one folder to another folder:

#Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/marketing"
$SourceURL = "/sites/marketing/Shared Documents/Active/SRS.docx"
$TargetURL = "/sites/marketing/Shared Documents/Categorized/SRS.docx"

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Interactive
 
#Copy All Files and Folders from one folder to another
Copy-PnPFile -SourceUrl $SourceURL -TargetUrl $TargetURL -Force

The Copy-PnPFile cmdlet can be used to copy a file to the same library or between libraries in different site collections!

#Config Variables
$SiteURL = "https://Crescent.sharepoint.com/sites/marketing"
$SourceURL= "Shared Documents/Discloser Asia.doc" #Site Relative path
$TargetURL = "/Sites/Sales/Shared Documents/Discloser Asia-v2.doc"

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Credentials (Get-Credential)

#Copy File to another site collection
Copy-PnPFile -SourceUrl $SourceURL -TargetUrl $TargetURL -Force 

If you need to copy files between different site collections, use: SharePoint Online: Copy Files Between Site Collections using PowerShell

Copy Folders Between Document Libraries using PnP PowerShell

What if you want to copy all files and sub-folders between two folders?

#Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/marketing"
$SourceFolderURL = "/sites/marketing/Shared Documents/V1"
$TargetFolderURL = "/sites/marketing/Project Document/V1"

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Credentials (Get-Credential) #-Interactive

#Copy All Files and Folders from one folder to another
Copy-PnPFile -SourceUrl $SourceFolderURL -TargetUrl $TargetFolderURL -Force

However, This method doesn’t work for the “RootFolder” object! (Meaning: You can’t just call this cmdlet to copy all files and folders between document libraries).

PnP PowerShell to Copy All Files and Folders Between Document Libraries with Metadata

Want to preserve the metadata while copying all items between libraries? No problem! Let me show you how to create a simple PowerShell script that you can use to copy files in SharePoint Online. Assuming we have both the source and destination document libraries in place, this PowerShell script copies everything from the source to the destination library along with its metadata.

#Function to copy all Items from one library to another
Function Copy-AllDocuments($SourceLibraryName, $TargetLibraryName)
{
    #Get Source and Target Libraries
    $SourceLibrary = Get-PnPList -Identity $SourceLibraryName -Includes RootFolder
    $TargetLibrary = Get-PnPList -Identity $TargetLibraryName -Includes RootFolder
 
    $Web = Get-PnPWeb
    #Calculate Site Relative URL of the Folder
    If($Web.ServerRelativeURL -eq "/")
    {
	    $FolderSiteRelativeUrl = $SourceLibrary.RootFolder.ServerRelativeUrl
    }
    Else
    {      
	    $FolderSiteRelativeUrl = $SourceLibrary.RootFolder.ServerRelativeUrl.Replace($Web.ServerRelativeURL,[string]::Empty)
    }

    #Get All Content from Source Library's Root Folder
    $RootFolderItems = Get-PnPFolderItem -FolderSiteRelativeUrl $FolderSiteRelativeUrl | Where {($_.Name -ne "Forms") -and (-Not($_.Name.StartsWith("_")))}
        
    #Copy Items to the Destination
    $RootFolderItems | ForEach-Object {
        $TargetURL = $TargetLibrary.RootFolder.ServerRelativeUrl
        Copy-PnPFile -SourceUrl $_.ServerRelativeUrl -TargetUrl $TargetURL -Force -OverwriteIfAlreadyExists
        Write-host "`tCopied '$($_.ServerRelativeUrl)'" -f Green    
    }
 
    #Get All Items from Source Library
    $SourceItems = Get-PnPListItem -List $SourceLibraryName -PageSize 500
    $TargetItems = Get-PnPListItem -List $TargetLibraryName -PageSize 500

    ForEach($SourceItem in $SourceItems)
    {
        #Get Metadata from Source Items
        $Metadata = @{
            'Title' = $SourceItem.FieldValues.Title
            'Created'= $SourceItem.FieldValues.Created.DateTime
            'Modified' = $SourceItem.FieldValues.Modified.DateTime
            'Author' = $SourceItem.FieldValues.Author.Email
            'Editor' = $SourceItem.FieldValues.Editor.Email
            }
        #Update Metadata in Target Items
        ForEach($TargetItem in $TargetItems)
        {
            If($SourceItem.FieldValues.FileLeafRef -eq $TargetItem.FieldValues.FileLeafRef)
            {
                Set-PnPListItem -List $TargetLibrary -Identity $TargetItem.Id -Values $Metadata | Out-Null
            }
        }
    }
}
#Connect to PnP Online
$SiteURL = "https://crescent.sharepoint.com/sites/Retail"
Connect-PnPOnline -Url $SiteURL -Interactive
#Call the function to copy all files between document libraries
Copy-AllDocuments -SourceLibraryName "Invoices" -TargetLibraryName "Invoices V2"

This script copies all files and folders between the given document libraries. To copy an entire document library to another site in SharePoint Online, use: SharePoint Online Copy Document library to another site PowerShell

Salaudeen Rajack

Salaudeen Rajack - Information Technology Expert with Two-decades of hands-on experience, specializing in SharePoint, PowerShell, Microsoft 365, and related products. He has held various positions including SharePoint Architect, Administrator, Developer and consultant, has helped many organizations to implement and optimize SharePoint solutions. Known for his deep technical expertise, He's passionate about sharing the knowledge and insights to help others, through the real-world articles!

10 thoughts on “SharePoint Online: Copy File Between Document Libraries using PowerShell

  • I keep getting this error for all lines:
    Set-PnPListItem : The string was not recognized as a valid DateTime. There is an unknown word starting at index 0.
    At line:46 char:15
    + … { Set-PnPListItem -List $TargetLibrary -Identity $TargetIte …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : WriteError: (:) [Set-PnPListItem], ServerException
    + FullyQualifiedErrorId : EXCEPTION,PnP.PowerShell.Commands.Lists.SetListItem

    Any insight in what could cause this.
    I can copy all files, but meta data transfer fails 🙁

    Reply
  • Hi!
    I am trying to use your script but I have too many files to move from one site to as subsite. How would I add a date range to your script? Thank you in Advance!

    Reply
  • Hi, is there any way to copy files with metadata between site collections using PnP module? I see you have used PnP module to copy in one site collection with metadata but I need to copy beetwen. Do you have any suggestions how to make it ?

    Reply
  • We need to copy multiple files (over 400) from various locations in our farm to a single document library. Is it possible to use a csv containing the urls as a parameter?

    Reply
      • Hello, do you have any examples of this? We also have the same requirement but couldn’t see anything relatable in your CSV section.

        Reply
  • Hi all,
    I’ve spent several weeks trying to figure out how to copy content between SharePoint Communications Sites. I have been succesful with pages and images (correction most images), but have failed to copy files and themes. I’ve been using PowerShell and Power Automate and also attempted using the code shown in your thread below. As I am still a relative novice with SharePoint admin, are there certain limitations that I need to know about before files can be moved (for instance do both sites need to be made public?)
    Any guidance would be appreciated.
    David

    Reply
  • I need to retain unique permissions set on all files and folders. Can your code accomplish that?

    Reply
  • So for my need – i am trying to copy(word docs) a specific combinations of files only from one site collection to another folder in different site collection along with metadata in online environment.Also the word doc has huge metadata list that need to copy along with file.Is it possible to specify that long list of metadata in script to copy and there are nearly different content types.So each time while copying we need to modify the script along with metadata of word doc
    and then run the script
    Please advise.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *