PowerShell script to copy SharePoint Online library with content types, fields and custom permission levels
Kavali Rakesh (H1B holder with valid work Authorization)
Senior SharePoint Online Developer | Office 365 | Power Platform | PowerApps | Power Automate | PowerBI | Migration Expert | SPFX | React | Team Lead | Frontend Developer | ASP.NET MVC | .NET Core
This PowerShell script can be used to copy a SharePoint Online library, along with its content types, fields, groups, and custom permission levels, from a source site to a destination site. The script also copies the items from the source library to the destination library, along with their metadata and permissions.
// Connect to SharePoint Online site
$sourceSiteUrl = "https://SourceSiteUrl.sharepoint.com"
$destinationSiteUrl = "https://DestinationSiteUrl.sharepoint.com"
Connect-SPOService -Url $sourceSiteUrl
Connect-SPOService -Url $destinationSiteUrl
?
// Set variables for the source and destination libraries
$sourceLibraryTitle = "Source Library Title"
$destinationLibraryTitle = "Destination Library Title"
?
// Get the source list and items
$sourceList = Get-SPOList -Identity $sourceLibraryTitle -Includes Fields, ContentTypes
$sourceItems = Get-SPOListItem -List $sourceLibraryTitle -Limit All -Includes RoleAssignments, HasUniqueRoleAssignments, Folder, FieldValuesAsHtml
?
// Create the destination library if it doesn't exist
if (!(Get-SPOList -Identity $destinationLibraryTitle -ErrorAction SilentlyContinue)) {
??? New-SPOList -Title $destinationLibraryTitle -Template DocumentLibrary
}
$destinationList = Get-SPOList -Identity $destinationLibraryTitle -Includes Fields, ContentTypes
?
// Copy the content types from the source to the destination
foreach ($ct in $sourceList.ContentTypes) {
??? $destCT = Get-SPOContentType -Name $ct.Name -List $destinationList
??? if (!$destCT) {
??????? Add-SPOContentTypeToList -List $destinationList -ContentType $ct.Name
??? }
}
?
// Copy the fields from the source to the destination
foreach ($field in $sourceList.Fields) {
??? $destField = Get-SPOField -Identity $field.InternalName -List $destinationList -ErrorAction SilentlyContinue
??? if (!$destField) {
??????? Add-SPOField -List $destinationList -DisplayName $field.Title -InternalName $field.InternalName -Type $field.TypeAsString -Required $field.Required
??? }
}
?
// Copy the SharePoint groups from the source to the destination
$sourceGroups = Get-SPOGroup -Site $sourceSiteUrl
foreach ($group in $sourceGroups) {
??? $destinationGroup = Get-SPOGroup -Site $destinationSiteUrl -Identity $group.LoginName
??? if (!$destinationGroup) {
??????? New-SPOGroup -Site $destinationSiteUrl -Name $group.Title -Description $group.Description
??? }
}
?
// Copy the custom permission levels from the source to the destination
$sourcePermissionLevels = Get-SPOPermissionLevel -Site $sourceSiteUrl
foreach ($level in $sourcePermissionLevels) {
??? $destinationLevel = Get-SPOPermissionLevel -Site $destinationSiteUrl -Identity $level.Name
??? if (!$destinationLevel) {
??????? New-SPOPermissionLevel -Site $destinationSiteUrl -Name $level.Name -Description $level.Description -BasePermissions $level.BasePermissions
??? }
}
?
// Copy the items from the source to the destination
foreach ($sourceItem in $sourceItems) {
??? // Copy the item to the destination library
??? $itemUrl = $sourceItem.FieldValuesAsHtml.FileRef.Split(",")[0]
??? $targetUrl = $destinationList.RootFolder.ServerRelativeUrl + "/" + $itemUrl.Split("/")[-1]
??? Copy-SPOFile -SourceUrl $itemUrl -TargetUrl $targetUrl -Force
?
??? // Set the metadata on the destination item
??? $destinationItem = Get-SPOListItem -List $destinationLibraryTitle -ItemId $sourceItem.Id
??? foreach ($field in $sourceItem.FieldValues.Keys) {
??????? if ($field -ne "ID" -and $field -ne "Created" -and $field -ne "Author" -and $field -ne "Modified" -and $field -ne "Editor") {
??????????? $destinationItem[$field] = $sourceItem[$field]
??????? }
??? }
??? $destinationItem.Update()
?
??? // Set the permissions on the destination item
??? $sourceItemUrl = $sourceItem.FieldValuesAsHtml.FileRef.Split(",")[0]
??? $sourceItemPermission = Get-SPOUserEffectivePermissions -Site $sourceSiteUrl -User $sourceItem["Editor"] -WebRelativeUrl $sourceItemUrl
?? ?$destinationItemUrl = $destinationItem.FieldValuesAsHtml.FileRef.Split(",")[0]
??? $destinationItemPermission = $null
?
??? // Create the SharePoint group if it doesn't exist in the destination site
??? $sourceItemEditorsGroup = Get-SPOGroup -Site $sourceSiteUrl -Identity $sourceItemPermission.Groups[0].LoginName -ErrorAction SilentlyContinue
??? $destinationItemEditorsGroup = Get-SPOGroup -Site $destinationSiteUrl -Identity $sourceItemPermission.Groups[0].LoginName -ErrorAction SilentlyContinue
??? if (!$destinationItemEditorsGroup) {
??????? New-SPOGroup -Site $destinationSiteUrl -Name $sourceItemPermission.Groups[0].Title -Description $sourceItemPermission.Groups[0].Description
??? }
?
??? // Set the permission level on the destination item
??? $sourceItemEditorsGroup = Get-SPOGroup -Site $sourceSiteUrl -Identity $sourceItemPermission.Groups[0].LoginName
??? $destinationItemEditorsGroup = Get-SPOGroup -Site $destinationSiteUrl -Identity $sourceItemPermission.Groups[0].LoginName
??? $permissionLevels = Get-SPOPermissionLevel -Site $sourceSiteUrl
??? foreach ($level in $permissionLevels) {
??????? if ($sourceItemPermission.RoleAssignments.RoleDefinitionBindings.Name -contains $level.Name) {
??????????? $destinationPermissionLevel = Get-SPOPermissionLevel -Site $destinationSiteUrl -Identity $level.Name
??????????? Set-SPOListItemPermission -List $destinationList -ItemId $destinationItem.Id -Group $destinationItemEditorsGroup -PermissionLevel $destinationPermissionLevel
??????????? break
??????? }
??? }
}