Moving a SharePoint folder and contents to different location in same Document Library

耗尽温柔 提交于 2019-12-03 16:04:25

There is no built-in method in SharePoint CSOM API for moving Folder with Files from one location into another.

The following class represents how to move files from source folder into destination folder:

public static class FolderExtensions
{


    public static void MoveFilesTo(this Folder folder, string folderUrl)
    {
        var ctx = (ClientContext)folder.Context;
        if (!ctx.Web.IsPropertyAvailable("ServerRelativeUrl"))
        {
            ctx.Load(ctx.Web, w => w.ServerRelativeUrl);   
        }
        ctx.Load(folder, f => f.Files, f => f.ServerRelativeUrl, f => f.Folders);
        ctx.ExecuteQuery();

        //Ensure target folder exists
        EnsureFolder(ctx.Web.RootFolder, folderUrl.Replace(ctx.Web.ServerRelativeUrl, string.Empty));
        foreach (var file in folder.Files)
        {
            var targetFileUrl = file.ServerRelativeUrl.Replace(folder.ServerRelativeUrl, folderUrl);
            file.MoveTo(targetFileUrl, MoveOperations.Overwrite);
        }
        ctx.ExecuteQuery();

        foreach (var subFolder in folder.Folders)
        {
            var targetFolderUrl = subFolder.ServerRelativeUrl.Replace(folder.ServerRelativeUrl,folderUrl);
            subFolder.MoveFilesTo(targetFolderUrl);
        }
    }


    public static Folder EnsureFolder(Folder parentFolder, string folderUrl)
    {
        var ctx = parentFolder.Context;
        var folderNames = folderUrl.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
        var folderName = folderNames[0];
        var folder = parentFolder.Folders.Add(folderName);
        ctx.Load(folder);
        ctx.ExecuteQuery();

        if (folderNames.Length > 1)
        {
            var subFolderUrl = string.Join("/", folderNames, 1, folderNames.Length - 1);
            return EnsureFolder(folder, subFolderUrl);
        }
        return folder;
    }
}

Key points:

  • allows to ensure whether destination folder(s) exists
  • In case of nested folders, its structure is preserved while moving files

Usage

var srcFolderUrl = "/news/pages";
var destFolderUrl = "/news/archive/pages";
using (var ctx = new ClientContext(url))
{      
    var sourceFolder = ctx.Web.GetFolderByServerRelativeUrl(srcFolderUrl);
    sourceFolder.MoveFilesTo(destFolderUrl);
    sourceFolder.DeleteObject(); // delete source folder if nessesary
    ctx.ExecuteQuery();
}
Guðjón Örn Þorsteinsson

Just in case someone needs this translated to PnP PowerShell. It's not battle tested but works for me. Versions and metadata moved as well within the same library.

$list = Get-PnPList -Identity Documents
$web = $list.ParentWeb
$folder = Ensure-PnPFolder -Web $list.ParentWeb -SiteRelativePath "Shared Documents/MoveTo"
$tofolder = Ensure-PnPFolder -Web $list.ParentWeb -SiteRelativePath "Shared Documents/MoveTwo"

function MoveFolder
{
    [cmdletbinding()]
    Param (
        $web,
        $fromFolder,
        $toFolder
    )
    $fromFolder.Context.Load($fromFolder.Files)
    $fromFolder.Context.Load($fromFolder.Folders)
    $fromFolder.Context.ExecuteQuery()
    foreach ($file in $fromFolder.Files)
    {
        $targetFileUrl = $file.ServerRelativeUrl.Replace($fromFolder.ServerRelativeUrl, $toFolder.ServerRelativeUrl);
        $file.MoveTo($targetFileUrl, [Microsoft.SharePoint.Client.MoveOperations]::Overwrite);
    }
    $fromFolder.Context.ExecuteQuery();

    foreach ($subFolder in $fromFolder.Folders)
    {
        $targetFolderUrl = $subFolder.ServerRelativeUrl.Replace($fromFolder.ServerRelativeUrl, $toFolder.ServerRelativeUrl);
        $targetFolderRelativePath = $targetFolderUrl.SubString($web.RootFolder.ServerRelativeUrl.Length)
        $tofolder = Ensure-PnPFolder -Web $list.ParentWeb -SiteRelativePath $targetFolderRelativePath
        MoveFolder -Web $web -fromFolder $subFolder -toFolder $tofolder
    }
}

$web.Context.Load($web.RootFolder)
$web.Context.ExecuteQuery()
MoveFolder -Web $web -fromFolder $folder -toFolder $tofolder
$folder.DeleteObject()
$web.Context.ExecuteQuery()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!