1

I have got a SharePoint library with a lot of files, which need to migrated to another site. The library includes some additional columns for each file (e.g. customer the file is related to, technology used, language, etc.).

I have created a new library in the target site and created all the columns for the additional information (customer, technology, language, etc.). I then copied a file using:

Copy-PnPFile -SourceUrl "/Path/to/file" -TargetUrl "/New/Path/"

The file was copied fine and for some columns the information is correct. But in most columns the information is messed up or empty. For example, the technology column, which is of type "Choice", should read "PowerApps", but now reads "12;#PowerApps" and if I look into the details it just says "12". Many other columns are of type "Managed Data". After the copy all of these are empty.

Can somebody point me in the right direction, why not all of the data is displayed correctly? Do I need to change the columns data type or is something wrong with the way I transfer the files?

2
  • What is the type of the colums (lookup, dropdown) ?
    – a1mery
    Feb 28, 2020 at 18:33
  • There are different ones. Thanks to your comment I had a look. Most of them are Managed Data. But the Managed Data ones are all empty after the copy. Some Choice columns work, while other Choice columns show the error stated above.
    – redleo85
    Feb 29, 2020 at 15:41

1 Answer 1

0

Please refer below code to copy all files from one library to another library in different site along with Metadata values:

#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-AllFilesWithMetadata
{
  param
    (
        [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
        $SourceFolder.Context.Load($SourceFilesColl)
        $SourceFolder.Context.ExecuteQuery()

        #Iterate through each file and copy
        Foreach($SourceFile in $SourceFilesColl)
        {
            #Get the source file
            $FileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($SourceFolder.Context, $SourceFile.ServerRelativeUrl)

            #Copy File to the Target location
            $TargetFileURL = $TargetFolder.ServerRelativeUrl+"/"+$SourceFile.Name
            [Microsoft.SharePoint.Client.File]::SaveBinaryDirect($TargetFolder.Context, $TargetFileURL, $FileInfo.Stream,$True)

            #Copy Metadata field values
            $SourceListItem = $SourceFile.ListItemAllFields
            $SourceFolder.Context.Load($SourceListItem)
            $SourceFolder.Context.ExecuteQuery()

            #Get the new file created
            $TargetFile = $TargetFolder.Context.Web.GetFileByServerRelativeUrl($TargetFileURL)
            $TargetListItem = $TargetFile.ListItemAllFields

            #Set Metadata values from the source
            $Author =$TargetFolder.Context.web.EnsureUser($SourceListItem["Author"].Email)
            $TargetListItem["Author"] = $Author
            $Editor =$TargetFolder.Context.web.EnsureUser($SourceListItem["Editor"].Email)
            $TargetListItem["Editor"] = $Editor
            $TargetListItem["Created"] = $SourceListItem["Created"]
            $TargetListItem["Modified"] = $SourceListItem["Modified"]
            $TargetListItem.Update()
            $TargetFolder.Context.ExecuteQuery()

            Write-host -f Green "Copied File '$($SourceFile.ServerRelativeUrl)' to '$TargetFileURL'"
        }

        #Process Sub Folders
        $SubFolders = $SourceFolder.Folders
        $SourceFolder.Context.Load($SubFolders)
        $SourceFolder.Context.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=$TargetFolder.Context.web.GetFolderByServerRelativeUrl($TargetFolderURL)
                        $TargetFolder.Context.load($Folder)
                        $TargetFolder.Context.ExecuteQuery()
                    }
                catch {
                        #Create Folder
                        if(!$Folder.Exists)
                        {
                            $TargetFolderURL
                            $Folder=$TargetFolder.Context.web.Folders.Add($TargetFolderURL)
                            $TargetFolder.Context.Load($Folder)
                            $TargetFolder.Context.ExecuteQuery()
                            Write-host "Folder Added:"$SubFolder.Name -f Yellow
                        }
                    }
                #Call the function recursively
                Copy-AllFilesWithMetadata -SourceFolder $SubFolder -TargetFolder $Folder
            }
        }
    }
    Catch {
        write-host -f Red "Error Copying File!" $_.Exception.Message
    }
}

#Set Parameter values
$SourceSiteURL="https://crescent.sharepoint.com/sites/sales"
$TargetSiteURL="https://crescent.sharepoint.com/sites/Ops"

$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 contexts
$SourceCtx = New-Object Microsoft.SharePoint.Client.ClientContext($SourceSiteURL)
$SourceCtx.Credentials = $Credentials
$TargetCtx = New-Object Microsoft.SharePoint.Client.ClientContext($TargetSiteURL)
$TargetCtx.Credentials = $Credentials

#Get the source library and Target Libraries
$SourceLibrary = $SourceCtx.Web.Lists.GetByTitle($SourceLibraryName)
$SourceCtx.Load($SourceLibrary)
$SourceCtx.Load($SourceLibrary.RootFolder)

$TargetLibrary = $TargetCtx.Web.Lists.GetByTitle($TargetLibraryName)
$TargetCtx.Load($TargetLibrary)
$TargetCtx.Load($TargetLibrary.RootFolder)
$TargetCtx.ExecuteQuery()

#Call the function
Copy-AllFilesWithMetadata -SourceFolder $SourceLibrary.RootFolder -TargetFolder $TargetLibrary.RootFolder

Reference:

https://www.sharepointdiary.com/2017/02/sharepoint-online-copy-files-between-site-collections-using-powershell.html

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.