question

techcons-0307 avatar image
0 Votes"
techcons-0307 asked techcons-0307 commented

Copy and mirror folder structure permissions on Sharepoint online site

Hello!

I need to mirror the source folder structure with permissions to destination folder (with inheritance) on Sharpeoint site. I have found the script on the web, which execution ends with:

Error Granting permission to Folder! Exception calling "ExecuteQuery" with "0" argument (s): "The 'Shared Documents' list does not exist on the site with the URL ..'."

 Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
 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.Taxonomy.dll"
 ########################################
 #### Connection Funtions  #############
 ########################################
    
 function Connect-SPO()
 {
     param ([Parameter(Mandatory=$true,Position=1)][string]$Username,[Parameter(Mandatory=$true,Position=2)][string]$Url,[Parameter(Mandatory=$true,Position=3)]$AdminPassword)
     $global:ctx=New-Object Microsoft.SharePoint.Client.ClientContext($Url)
     $ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Username, $AdminPassword)
     $ctx.Load($ctx.Web)
     $ctx.ExecuteQuery()
 }
    
 ########################################
 #### Recurse Function  #################
 ########################################      
 function Recurse($Folder) 
 {
 $Host.Runspace.ThreadOptions = "ReuseThread"
    
     $folderName = $Folder.Name
     $folderItemCount = $folder.ItemCount
     Write-Host "Folder Name ->'$folderName'"
     Write-Host "Number of List Items->'$folderItemCount'"
    
    
     if($Folder.name -eq $SrcFolderName)
     {
    
           $Rootfolderurl= $Folder.ServerRelativeUrl
           $NewRootFolder=$RootfolderURl.Replace($SrcFolderName,$NewFolderName)
           Write-Host $Rootfolderurl -ForegroundColor Magenta
           Write-Host $NewRootFolder -ForegroundColor Magenta
    
    
           ###########################
           #Create the new Root Folder
           ##########################
           ###Create-Folder -LibraryName $LibraryName -FolderName $NewFolderName -RootPermissionCol $RootPermissionCopy
    
    
           #Create the Folder
           $CreateNewFolder=$ctx.Web.Folders.Add($NewRootFolder)
           $ctx.ExecuteQuery()
           Write-Host "Folder Created"
    
           #############################
           ###Get Security on RootFolder
           #############################
    
           $RootPermissionCopy=  Get-SPOFolderPermission -FolderRelativeURL $Rootfolderurl
    
           #############################
           ###Break Inheritence on New Root Folder
           #############################
    
           $cFolder = $ctx.Web.GetFolderByServerRelativeUrl($NewRootFolder)
           $ctx.Load($cFolder)
           $ctx.ExecuteQuery()
    
            #Break Permission inheritence - Remove all existing list permissions & keep Item level permissions
            $cFolder.ListItemAllFields.BreakRoleInheritance($False,$True)
            $ctx.ExecuteQuery()
    
    
           foreach($Permission in $RootPermissionCopy)
           {
               Write-Host "Name " $Permission.Name
               Write-Host "Type " $Permission.Type
               Write-Host "Permission Levels" $Permission.PermissionLevels
    
    
    
               #Check and Skip if Permission are only "Limited Access"
               If ($Permission.PermissionLevels -eq "Limited Access") {
               Write-Host "Skipping because there is only Limited Access"
               Write-Host ""
               }
               Else {
                 if($Permission.Type -eq "User"){
                     $PermLevelArray=$Permission.PermissionLevels -split ","
                     $UserAccount =$Permission.Name
                     $User = $ctx.Web.EnsureUser($UserAccount)
                     $ctx.load($User)
                     $ctx.ExecuteQuery()
    
                         Foreach($PermLevel in $PermLevelArray){
                             write-host $PermLevel
                             if($PermLevel -eq "Limited Access") {
                                 Write-Host "Skipping Limited Access"
                             }
                             Else {
                                 $Role = $ctx.Web.RoleDefinitions.GetByName($PermLevel)
                                 $RoleDB = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)
                                 $RoleDB.Add($Role)
                                 $UserPermissions = $cFolder.ListItemAllFields.RoleAssignments.Add($User,$RoleDB)
                                 Write-Host "Applied " $PermLevel
                                 $cFolder.Update()
                                     try {
                                         $ctx.ExecuteQuery()
                                     }
                                     Catch {
                                         Write-host "User cannot be found"
                                     }
                             }
                         }
                 }
                 else{
                     Write-host $Permission.Name
                     $PermLevelArray=$Permission.PermissionLevels -split ","
                     $GroupName = $Permission.Name
                     $Group =$ctx.Web.SiteGroups.GetByName($GroupName)
                     $ctx.load($Group)
                     $ctx.ExecuteQuery()
    
                     Foreach($PermLevel in $PermLevelArray){
                         write-host $PermLevel
                         if($PermLevel -eq "Limited Access") {
                             Write-Host "Skipping Limited Access"
                         }
                         Else {
                             $Role = $ctx.Web.RoleDefinitions.GetByName($PermLevel)
                             $RoleDB = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)
                             $RoleDB.Add($Role)
                             $GroupPermissions = $cFolder.ListItemAllFields.RoleAssignments.Add($Group,$RoleDB)
                             Write-Host "Applied " $PermLevel
                             $cFolder.Update()
                             Try {
                                 $ctx.ExecuteQuery()
                             }
                             Catch {
                                 Write-host "Group Cannot be Found"
                             }
                        }
                     }
                 }
    
               }
    
           }
    
           Write-Host "Permissions Retrieved"
    
    
     }
    
     Else
     {
     ################################
     ##Create New SubFolder
     ################################
    
        Write-Host "Copy this folder as a none root folder!!" -ForegroundColor Cyan
    
        #Get Relative Url of the Folder to Copy
        $CurrentFolderUrl= $Folder.ServerRelativeUrl
        Write-Host $CurrentFolderUrl -ForegroundColor Green
    
        #Create Url of the Folder to Create based on the Current Folder - Replace Folder Path
        $FolderToAdd = $CurrentFolderUrl.Replace($SrcFolderName,$NewFolderName)
        Write-Host "Add===> "$FolderToAdd -ForegroundColor Cyan
    
    
    
        #Create the Folder
        $CreateNewFolder=$ctx.Web.Folders.Add($FolderToAdd)
        $ctx.ExecuteQuery()
        Write-Host "Folder Created"
    
        #############################
        ###Get Security on Current Folder
        #############################
        $CurrentPermissionCopy=  Get-SPOFolderPermission -FolderRelativeURL $CurrentFolderUrl
    
        #############################
        ###Break Inheritence on New Root Folder
        #############################
    
        $cFolder = $ctx.Web.GetFolderByServerRelativeUrl($FolderToAdd)
        $ctx.Load($cFolder)
        $ctx.ExecuteQuery()
    
        #Break Permission inheritence - Remove all existing list permissions & keep Item level permissions
        $cFolder.ListItemAllFields.BreakRoleInheritance($False,$True)
        $ctx.ExecuteQuery()
    
    
           foreach($Permission in $CurrentPermissionCopy)
           {
               Write-Host "Name " $Permission.Name
               Write-Host "Type " $Permission.Type
               Write-Host "Permission Levels" $Permission.PermissionLevels
    
    
    
               #Check and Skip if Permission are only "Limited Access"
               If ($Permission.PermissionLevels -eq "Limited Access") {
               Write-Host "Skipping because there is only Limited Access"
               Write-Host ""
               }
               Else {
                 if($Permission.Type -eq "User"){
                     $PermLevelArray=$Permission.PermissionLevels -split ","
                     $UserAccount =$Permission.Name
                     $User = $ctx.Web.EnsureUser($UserAccount)
                     $ctx.load($User)
                     $ctx.ExecuteQuery()
    
                         Foreach($PermLevel in $PermLevelArray){
                             write-host $PermLevel
                             if($PermLevel -eq "Limited Access") {
                                 Write-Host "Skipping Limited Access"
                             }
                             Else {
                                 $Role = $ctx.Web.RoleDefinitions.GetByName($PermLevel)
                                 $RoleDB = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)
                                 $RoleDB.Add($Role)
                                 $UserPermissions = $cFolder.ListItemAllFields.RoleAssignments.Add($User,$RoleDB)
                                 Write-Host "Applied " $PermLevel
                                 $cFolder.Update()
                                     try {
                                         $ctx.ExecuteQuery()
                                     }
                                     Catch {
                                         Write-host "User cannot be found"
                                     }
                             }
                         }
                 }
                 else{
                     Write-host $Permission.Name
                     $PermLevelArray=$Permission.PermissionLevels -split ","
                     $GroupName = $Permission.Name
                     $Group =$ctx.Web.SiteGroups.GetByName($GroupName)
                     $ctx.load($Group)
                     $ctx.ExecuteQuery()
    
                     Foreach($PermLevel in $PermLevelArray){
                         write-host $PermLevel
                        if($PermLevel -eq "Limited Access") {
                             Write-Host "Skipping Limited Access"
                         }
                         Else {
                             $Role = $ctx.Web.RoleDefinitions.GetByName($PermLevel)
                             $RoleDB = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)
                             $RoleDB.Add($Role)
                             $GroupPermissions = $cFolder.ListItemAllFields.RoleAssignments.Add($Group,$RoleDB)
                             Write-Host "Applied " $PermLevel
                             $cFolder.Update()
                             Try {
                                 $ctx.ExecuteQuery()
                             }
                             Catch {
                                 Write-host "Group Cannot be Found"
                             }
                        }
                     }
                 }
    
               }
    
           }
    
        }
    
    
    
     #Write-Host $folder.ListItemAllFields.HasUniqueRoleAssignments
     $thisFolder = $ctx.Web.GetFolderByServerRelativeUrl($Folder.ServerRelativeUrl)
     $ctx.Load($thisFolder)
     $ctx.Load($thisFolder.Folders)
     $ctx.ExecuteQuery()
    
     foreach($subfolder in $thisFolder.Folders)
         {
            Write-Host $subfolder.ServerRelativeUrl -ForegroundColor Gray
             Recurse $subfolder  
         }       
 }
    
 ##########################################
 #### Function to Get Folder Permissions ## 
 ##########################################
 Function Check-SPOFolderExists()
 {
   param
     ( [Parameter(Mandatory=$true)] [string] $FolderRelativeURL)
    
     $Host.Runspace.ThreadOptions = "ReuseThread"
        $checkfolderExists="False"
    
     Try {
           #Check Folder Exists
           $checkfolder= $ctx.web.GetFolderByServerRelativeUrl($FolderRelativeURL)
           $ctx.Load($Folder)
           $ctx.ExecuteQuery()
           $checkfolderExists="True";
           #Write-host -f Green "Folder Exists!"
         }
    
     catch{
            Write-host -f Yellow "Folder Doesn't Exist!"
             #Write-Host "Error in Check-SPoFolder Function with Message" $_.Exception.Message
         }
    
     return $checkfolderExists
    
  }
    
    
 ##########################################
 #### Function to Get Folder Permissions ## 
 ##########################################
    
 Function Get-SPOFolderPermission([String]$FolderRelativeURL)
 {
     $Host.Runspace.ThreadOptions = "ReuseThread"
     Try{
    
    
         #Get the Folder
         $pFolder = $ctx.Web.GetFolderByServerRelativeUrl($FolderRelativeURL)
         $ctx.Load($pFolder)
         $ctx.ExecuteQuery()
    
         #Get permissions assigned to the Folder
         $RoleAssignments = $pFolder.ListItemAllFields.RoleAssignments
         $ctx.Load($RoleAssignments)
         $ctx.ExecuteQuery()
    
         #Loop through each permission assigned and extract details
         $PermissionCollection = @()
         Foreach($RoleAssignment in $RoleAssignments)
        {
             $ctx.Load($RoleAssignment.Member)
             $ctx.executeQuery()
    
             #Get the User Type
             $PermissionType = $RoleAssignment.Member.PrincipalType
    
             #Get the Permission Levels assigned
             $ctx.Load($RoleAssignment.RoleDefinitionBindings)
             $ctx.ExecuteQuery()
    
    
                     $PermissionLevels = ($RoleAssignment.RoleDefinitionBindings | Select -ExpandProperty Name) -join ","
                     #Get the User/Group Name
                      $Name = $RoleAssignment.Member.LoginName # $RoleAssignment.Member.LoginName
    
                         #Add the Data to Object
                         $Permissions = New-Object PSObject
                         $Permissions | Add-Member NoteProperty Name($Name)
                         $Permissions | Add-Member NoteProperty Type($PermissionType)
                         $Permissions | Add-Member NoteProperty PermissionLevels($PermissionLevels)
                         $PermissionCollection += $Permissions
    
         }
         Return $PermissionCollection
     }
     Catch {
         write-host -f Red "Error Getting Folder Permissions!" $_.Exception.Message
     }
 }
    
 ##################################
 #### Parmeters and start script ## 
 ##################################
    
 $admin=""
 $pass= ConvertTo-SecureString "" -AsPlainText -Force
 $SiteURL="https://micrososft.sharepoint.com/sites/hgs_demo/"
 $LibraryName="FolderTest";
 $SrcFolderName="mytest"
 $NewFolderName="cmytesst"
 $global:ctx
 Try {
      Connect-SPO -Username $admin -Url $SiteURL -AdminPassword $pass
     $Library=$ctx.Web.Lists.GetByTitle($LibraryName);
     $Folders = $Library.RootFolder.Folders
     $ctx.Load($Library);
     $ctx.Load($Folders)
     $ctx.ExecuteQuery()   
    
     foreach ($Folder in $Library.RootFolder.Folders)
         {
    
         if($Folder.ItemCount -gt 0 -and $Folder.Name -eq $SrcFolderName)
          {
               $CurrentRootfolderurl= $Folder.ServerRelativeUrl
             $NewRootFolderUrl=$CurrentRootfolderurl.Replace($SrcFolderName,$NewFolderName)
           #CheckIfFolderExists
            $CheckRootFolderExists= Check-SPOFolderExists -FolderRelativeURL $NewRootFolderUrl
            if( $CheckRootFolderExists -eq "True")
            {
    
                Write-Host "A folder with name "$NewFolderName "already Exists and its url " $NewRootFolderUrl -ForegroundColor Green
            }
            else{
             #Calling Recursive Function with
                 Recurse $Folder
              }
            }
         }
    
    
    
     }
    
     catch{
    
     Write-Host  $_.Exception.Message
    
 }


Could you please help to solve the problem or there are another way / script to do it?

Thanks!




office-sharepoint-onlinesharepoint-dev
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi @techcons-0307,
I am currently doing some research on this issue, will let you know as soon as possible.

0 Votes 0 ·
RaytheonXie-MSFT avatar image
0 Votes"
RaytheonXie-MSFT answered RaytheonXie-MSFT edited

Hi @techcons-0307,
There some error in the function of connect to sharepoint online. I have modified some code and try following sample Please:

  ########################################
  #### Recurse Function  #################
  ########################################      
  function Recurse($Folder) 
  {
  $Host.Runspace.ThreadOptions = "ReuseThread"
        
      $folderName = $Folder.Name
      $folderItemCount = $folder.ItemCount
      Write-Host "Folder Name ->'$folderName'"
      Write-Host "Number of List Items->'$folderItemCount'"
        
        
      if($Folder.name -eq $SrcFolderName)
      {
        
            $Rootfolderurl= $Folder.ServerRelativeUrl
            $NewRootFolder=$RootfolderURl.Replace($SrcFolderName,$NewFolderName)
            Write-Host $Rootfolderurl -ForegroundColor Magenta
            Write-Host $NewRootFolder -ForegroundColor Magenta
        
        
            ###########################
            #Create the new Root Folder
            ##########################
            ###Create-Folder -LibraryName $LibraryName -FolderName $NewFolderName -RootPermissionCol $RootPermissionCopy
        
        
            #Create the Folder
            $CreateNewFolder=$ctx.Web.Folders.Add($NewRootFolder)
            $ctx.ExecuteQuery()
            Write-Host "Folder Created"
        
            #############################
            ###Get Security on RootFolder
            #############################
        
            $RootPermissionCopy=  Get-SPOFolderPermission -FolderRelativeURL $Rootfolderurl
        
            #############################
            ###Break Inheritence on New Root Folder
            #############################
        
            $cFolder = $ctx.Web.GetFolderByServerRelativeUrl($NewRootFolder)
            $ctx.Load($cFolder)
            $ctx.ExecuteQuery()
        
             #Break Permission inheritence - Remove all existing list permissions & keep Item level permissions
             $cFolder.ListItemAllFields.BreakRoleInheritance($False,$True)
             $ctx.ExecuteQuery()
        
        
            foreach($Permission in $RootPermissionCopy)
            {
                Write-Host "Name " $Permission.Name
                Write-Host "Type " $Permission.Type
                Write-Host "Permission Levels" $Permission.PermissionLevels
        
        
        
                #Check and Skip if Permission are only "Limited Access"
                If ($Permission.PermissionLevels -eq "Limited Access") {
                Write-Host "Skipping because there is only Limited Access"
                Write-Host ""
                }
                Else {
                  if($Permission.Type -eq "User"){
                      $PermLevelArray=$Permission.PermissionLevels -split ","
                      $UserAccount =$Permission.Name
                      $User = $ctx.Web.EnsureUser($UserAccount)
                      $ctx.load($User)
                      $ctx.ExecuteQuery()
        
                          Foreach($PermLevel in $PermLevelArray){
                              write-host $PermLevel
                              if($PermLevel -eq "Limited Access") {
                                  Write-Host "Skipping Limited Access"
                              }
                              Else {
                                  $Role = $ctx.Web.RoleDefinitions.GetByName($PermLevel)
                                  $RoleDB = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)
                                  $RoleDB.Add($Role)
                                  $UserPermissions = $cFolder.ListItemAllFields.RoleAssignments.Add($User,$RoleDB)
                                  Write-Host "Applied " $PermLevel
                                  $cFolder.Update()
                                      try {
                                          $ctx.ExecuteQuery()
                                      }
                                      Catch {
                                          Write-host "User cannot be found"
                                      }
                              }
                          }
                  }
                  else{
                      Write-host $Permission.Name
                      $PermLevelArray=$Permission.PermissionLevels -split ","
                      $GroupName = $Permission.Name
                      $Group =$ctx.Web.SiteGroups.GetByName($GroupName)
                      $ctx.load($Group)
                      $ctx.ExecuteQuery()
        
                      Foreach($PermLevel in $PermLevelArray){
                          write-host $PermLevel
                          if($PermLevel -eq "Limited Access") {
                              Write-Host "Skipping Limited Access"
                          }
                          Else {
                              $Role = $ctx.Web.RoleDefinitions.GetByName($PermLevel)
                              $RoleDB = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)
                              $RoleDB.Add($Role)
                              $GroupPermissions = $cFolder.ListItemAllFields.RoleAssignments.Add($Group,$RoleDB)
                              Write-Host "Applied " $PermLevel
                              $cFolder.Update()
                              Try {
                                  $ctx.ExecuteQuery()
                              }
                              Catch {
                                  Write-host "Group Cannot be Found"
                              }
                         }
                      }
                  }
        
                }
        
            }
        
            Write-Host "Permissions Retrieved"
        
        
      }
        
      Else
      {
      ################################
      ##Create New SubFolder
      ################################
        
         Write-Host "Copy this folder as a none root folder!!" -ForegroundColor Cyan
        
         #Get Relative Url of the Folder to Copy
         $CurrentFolderUrl= $Folder.ServerRelativeUrl
         Write-Host $CurrentFolderUrl -ForegroundColor Green
        
         #Create Url of the Folder to Create based on the Current Folder - Replace Folder Path
         $FolderToAdd = $CurrentFolderUrl.Replace($SrcFolderName,$NewFolderName)
         Write-Host "Add===> "$FolderToAdd -ForegroundColor Cyan
        
        
        
         #Create the Folder
         $CreateNewFolder=$ctx.Web.Folders.Add($FolderToAdd)
         $ctx.ExecuteQuery()
         Write-Host "Folder Created"
        
         #############################
         ###Get Security on Current Folder
         #############################
         $CurrentPermissionCopy=  Get-SPOFolderPermission -FolderRelativeURL $CurrentFolderUrl
        
         #############################
         ###Break Inheritence on New Root Folder
         #############################
        
         $cFolder = $ctx.Web.GetFolderByServerRelativeUrl($FolderToAdd)
         $ctx.Load($cFolder)
         $ctx.ExecuteQuery()
        
         #Break Permission inheritence - Remove all existing list permissions & keep Item level permissions
         $cFolder.ListItemAllFields.BreakRoleInheritance($False,$True)
         $ctx.ExecuteQuery()
        
        
            foreach($Permission in $CurrentPermissionCopy)
            {
                Write-Host "Name " $Permission.Name
                Write-Host "Type " $Permission.Type
                Write-Host "Permission Levels" $Permission.PermissionLevels
        
        
        
                #Check and Skip if Permission are only "Limited Access"
                If ($Permission.PermissionLevels -eq "Limited Access") {
                Write-Host "Skipping because there is only Limited Access"
                Write-Host ""
                }
                Else {
                  if($Permission.Type -eq "User"){
                      $PermLevelArray=$Permission.PermissionLevels -split ","
                      $UserAccount =$Permission.Name
                      $User = $ctx.Web.EnsureUser($UserAccount)
                      $ctx.load($User)
                      $ctx.ExecuteQuery()
        
                          Foreach($PermLevel in $PermLevelArray){
                              write-host $PermLevel
                              if($PermLevel -eq "Limited Access") {
                                  Write-Host "Skipping Limited Access"
                              }
                              Else {
                                  $Role = $ctx.Web.RoleDefinitions.GetByName($PermLevel)
                                  $RoleDB = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)
                                  $RoleDB.Add($Role)
                                  $UserPermissions = $cFolder.ListItemAllFields.RoleAssignments.Add($User,$RoleDB)
                                  Write-Host "Applied " $PermLevel
                                  $cFolder.Update()
                                      try {
                                          $ctx.ExecuteQuery()
                                      }
                                      Catch {
                                          Write-host "User cannot be found"
                                      }
                              }
                          }
                  }
                  else{
                      Write-host $Permission.Name
                      $PermLevelArray=$Permission.PermissionLevels -split ","
                      $GroupName = $Permission.Name
                      $Group =$ctx.Web.SiteGroups.GetByName($GroupName)
                      $ctx.load($Group)
                      $ctx.ExecuteQuery()
        
                      Foreach($PermLevel in $PermLevelArray){
                          write-host $PermLevel
                         if($PermLevel -eq "Limited Access") {
                              Write-Host "Skipping Limited Access"
                          }
                          Else {
                              $Role = $ctx.Web.RoleDefinitions.GetByName($PermLevel)
                              $RoleDB = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)
                              $RoleDB.Add($Role)
                              $GroupPermissions = $cFolder.ListItemAllFields.RoleAssignments.Add($Group,$RoleDB)
                              Write-Host "Applied " $PermLevel
                              $cFolder.Update()
                              Try {
                                  $ctx.ExecuteQuery()
                              }
                              Catch {
                                  Write-host "Group Cannot be Found"
                              }
                         }
                      }
                  }
        
                }
        
            }
        
         }
        
        
        
      #Write-Host $folder.ListItemAllFields.HasUniqueRoleAssignments
      $thisFolder = $ctx.Web.GetFolderByServerRelativeUrl($Folder.ServerRelativeUrl)
      $ctx.Load($thisFolder)
      $ctx.Load($thisFolder.Folders)
      $ctx.ExecuteQuery()
        
      foreach($subfolder in $thisFolder.Folders)
          {
             Write-Host $subfolder.ServerRelativeUrl -ForegroundColor Gray
              Recurse $subfolder  
          }       
  }
        
  ##########################################
  #### Function to Get Folder Permissions ## 
  ##########################################
  Function Check-SPOFolderExists()
  {
    param
      ( [Parameter(Mandatory=$true)] [string] $FolderRelativeURL)
        
      $Host.Runspace.ThreadOptions = "ReuseThread"
         $checkfolderExists="False"
        
      Try {
            #Check Folder Exists
            $checkfolder= $ctx.web.GetFolderByServerRelativeUrl($FolderRelativeURL)
            $ctx.Load($Folder)
            $ctx.ExecuteQuery()
            $checkfolderExists="True";
            #Write-host -f Green "Folder Exists!"
          }
        
      catch{
             Write-host -f Yellow "Folder Doesn't Exist!"
              #Write-Host "Error in Check-SPoFolder Function with Message" $_.Exception.Message
          }
        
      return $checkfolderExists
        
   }
        
        
  ##########################################
  #### Function to Get Folder Permissions ## 
  ##########################################
        
  Function Get-SPOFolderPermission([String]$FolderRelativeURL)
  {
      $Host.Runspace.ThreadOptions = "ReuseThread"
      Try{
        
        
          #Get the Folder
          $pFolder = $ctx.Web.GetFolderByServerRelativeUrl($FolderRelativeURL)
          $ctx.Load($pFolder)
          $ctx.ExecuteQuery()
        
          #Get permissions assigned to the Folder
          $RoleAssignments = $pFolder.ListItemAllFields.RoleAssignments
          $ctx.Load($RoleAssignments)
          $ctx.ExecuteQuery()
        
          #Loop through each permission assigned and extract details
          $PermissionCollection = @()
          Foreach($RoleAssignment in $RoleAssignments)
         {
              $ctx.Load($RoleAssignment.Member)
              $ctx.executeQuery()
        
              #Get the User Type
              $PermissionType = $RoleAssignment.Member.PrincipalType
        
              #Get the Permission Levels assigned
              $ctx.Load($RoleAssignment.RoleDefinitionBindings)
              $ctx.ExecuteQuery()
        
        
                      $PermissionLevels = ($RoleAssignment.RoleDefinitionBindings | Select -ExpandProperty Name) -join ","
                      #Get the User/Group Name
                       $Name = $RoleAssignment.Member.LoginName # $RoleAssignment.Member.LoginName
        
                          #Add the Data to Object
                          $Permissions = New-Object PSObject
                          $Permissions | Add-Member NoteProperty Name($Name)
                          $Permissions | Add-Member NoteProperty Type($PermissionType)
                          $Permissions | Add-Member NoteProperty PermissionLevels($PermissionLevels)
                          $PermissionCollection += $Permissions
        
          }
          Return $PermissionCollection
      }
      Catch {
          write-host -f Red "Error Getting Folder Permissions!" $_.Exception.Message
      }
  }
        
  ##################################
  #### Parmeters and start script ## 
  ##################################
        
  $admin="admin"
  $pass= ConvertTo-SecureString "password" -AsPlainText -Force
  $SiteURL="url"
  $LibraryName="FolderTest";
  $SrcFolderName="22"
  $NewFolderName="Document"
    
      
 #Get Credentials to connect to SharePoint Online site
 #$Cred = Get-Credential
    
 #$UserName="account"
 #$Password = "password"
        
 #Set up the context
 $ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl)
 $ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($admin, $pass)
      $Library=$ctx.Web.Lists.GetByTitle($LibraryName);
      $Folders = $Library.RootFolder.Folders
    
      $ctx.Load($Library);
      $ctx.Load($Folders)
      $ctx.ExecuteQuery()   
        
      foreach ($Folder in $Library.RootFolder.Folders)
          {
      $ctx.Load($Folder);
   $ctx.ExecuteQuery() 
          if($Folder.ItemCount -gt 0 -and $Folder.Name -eq $SrcFolderName)
           {
                $CurrentRootfolderurl= $Folder.ServerRelativeUrl
              $NewRootFolderUrl=$CurrentRootfolderurl.Replace($SrcFolderName,$NewFolderName)
            #CheckIfFolderExists
             $CheckRootFolderExists= Check-SPOFolderExists -FolderRelativeURL $NewRootFolderUrl
             if( $CheckRootFolderExists -eq "True")
             {
        
                 Write-Host "A folder with name "$NewFolderName "already Exists and its url " $NewRootFolderUrl -ForegroundColor Green
             }
             else{
              #Calling Recursive Function with
                  Recurse $Folder
               }
             }
          }


If an Answer is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.



5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

techcons-0307 avatar image
0 Votes"
techcons-0307 answered techcons-0307 commented

Hi,
thanks for the corrections. Now it works on library with latin characters with spaces. I have library name with Spanish characters and spaces (Documentación Principal) and the script does not work and ends with the same error. Is there any way to fix url without changing the folder name?
have tried


   $LibraryName="Documentacin Principal";
      $LibraryName="Documentación Principal";
      $LibraryName="Documentacin%20Principal"; 


· 7
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi @techcons-0307,
Per my test I added a cmd and run the code with Spanish characters successfully.

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12




0 Votes 0 ·

Thank you for clarification, seems that problem is with path, which is included more than one folder. (the next question)

    $SrcFolderName="11/111/111/22"
    $NewFolderName="11/111/111/Document"


0 Votes 0 ·

Hi @techcons-0307,
Since the $SrcFolderName and $NewFolderName are used as name in following code, We need to add a new parameter to use.

 $SrcFolderName="11/111/111/22"
 $NewFolderName="11/111/111/Document"
 $TargetUrl = "/sites/yousites/Document Lib/11/111/111"

Then we need to edit some code:
change

 $Folders = $Library.RootFolder.Folders

to

 $Folders = $ctx.Web.GetFolderByServerRelativeUrl($TargetUrl).Folders

change

 foreach ($Folder in $Library.RootFolder.Folders)

to

 foreach ($Folder in $Folders)

















0 Votes 0 ·
Show more comments

Hello,
just change the code.
II got the error.

 Exception calling "ExecuteQuery" with "0" argument(s): ""File not Found."."
 At C:\isi\folder-copy.ps1:387 char:11
 +           $ctx.ExecuteQuery()
 +           ~~~~~~~~~~~~~~~~~~~
     + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
     + FullyQualifiedErrorId : ServerException
    
 The collection has not been initialized. It has not been requested or the request has not been executed. It may need to
  be explicitly requested.
 At C:\isi\folder-copy.ps1:390 char:15
 +            foreach ($Folder in $Folders)
 +                     ~~~~~~~
     + CategoryInfo          : OperationStopped: (:) [], CollectionNotInitializedException
     + FullyQualifiedErrorId : Microsoft.SharePoint.Client.CollectionNotInitializedException

lline 390 is

   foreach ($Folder in $Folders)

where can be the problem?

0 Votes 0 ·
Show more comments
techcons-0307 avatar image
0 Votes"
techcons-0307 answered techcons-0307 edited

Also I can't find the answer how to do with folder structure if the folder to be copied is under the multiple folders path.
for example

   $SrcFolderName="11/111/111/22"
   $NewFolderName="11/111/111/Document"

I tried the way I wrote above but the script has ended without error and noting gets copied.
Thanks!

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.