SharePoint Online PnPProvisionning include document library file contents

For those of you who are familliar with PnP Provisioning you might have noticed that out of the box when you save a template and you want to apply your template to another site the document library contents is not included.

I will show you how to add some subroutines to include document library content in your template.xml file.

First we will connect to the target site and initialize some variable

Connect-PnPOnline -Url $siteURL -Credentials $credential; 
Write-Output "Connected!"

$web = Get-PnPWeb

$siteTitle = $web.Title

$saveDir = "C:\Template\" + $siteTitle + "\"

Then just trigger the Get-PnPProvisioningTemplate function 

Get-PnPProvisioningTemplate -Out $($saveDir + "Template.xml") -Force -PersistBrandingFiles -PersistPublishingFiles -IncludeNativePublishingFiles -Handlers Navigation, Lists,PageContents, Pages, Files

I am specifying only fice handlers but you can go with the defaults ones

This will create a Template.xml file but no references to files in any document library.

Now the fun begins

Using the Add-PnPFileToProvisioningTemplate command we will add entry in the Template.xml file to reference a file we want to include in our template. The idea her is to create a subroutine that will parse all the document libray in the site and read all the files and include a reference to those files in the Template.xml

This is how it can be done

First two subroutine to loop through all the folder and subfolder of a document libray

function ProcessFolder($folderUrl, $destinationFolder) {
	Write-Output "Folder URL " $folderUrl  " destinationFolder " $destinationFolder
    $folder = Get-PnPFolder -RelativeUrl $folderUrl
    $tempfiles = Get-PnPProperty -ClientObject $folder -Property Files
    if (!(Test-Path -path $destinationfolder )) {
        $dest = New-Item $destinationfolder -type directory 

    $total = $folder.Files.Count
    For ($i = 0; $i -lt $total; $i++) {
        $file = $folder.Files[$i]
        Get-PnPFile -ServerRelativeUrl $file.ServerRelativeUrl -Path $destinationfolder -FileName $file.Name -AsFile -Force	

		Add-PnPFileToProvisioningTemplate -Path ($saveDir + "Template.xml") -Source ($destinationfolder + "\" + $file.Name) -Folder $folderUrl -FileLevel Published

function ProcessSubFolders($folders, $currentPath) {
    foreach ($folder in $folders) {
        $tempurls = Get-PnPProperty -ClientObject $folder -Property ServerRelativeUrl    
        #Avoid Forms folders
        if ($folder.Name -ne "Forms") {
            $targetFolder = $currentPath +"\"+ $folder.Name;
            ProcessFolder $folder.ServerRelativeUrl.Substring($web.ServerRelativeUrl.Length) $targetFolder 
            $tempfolders = Get-PnPProperty -ClientObject $folder -Property Folders
            ProcessSubFolders $tempfolders $targetFolder

Note here the

Get-PnPFile -ServerRelativeUrl $file.ServerRelativeUrl -Path $destinationfolder -FileName $file.Name -AsFile -Force

This will download the file and save it in the destination folder locally. Then with 

Add-PnPFileToProvisioningTemplate -Path ($saveDir + "Template.xml") -Source ($destinationfolder + "\" + $file.Name) -Folder $folderUrl -FileLevel Published

it will add an entry to the Template.xml file referencing the file we just downloaded.

What is left now is to loop through all  the document libraries and call our subroutines

$docLibs = Get-PNPList | Where-Object{$_.BaseTemplate -eq 101}

    Write-Output "getting doc list"

    foreach( $doc in $docLibs ){

            if( $doc.Title -ne "Site Assets"){
                #Download root files
                ProcessFolder $doc.Title ($saveDir + $doc.Title)
                #Download files in folders
                $tempfolders = Get-PnPProperty -ClientObject $doc.RootFolder -Property Folders
                ProcessSubFolders $tempfolders $($saveDir + $doc.Title) + "\"

Here the $_.BaseTemplate -eq 101 is to get only document libraries and the $doc.Title -ne "Site Assets" is just to skip the Site Assets library.

Now you have a beautifull Template.xml file with all your document library files references. You just need to apply it to another site with

Connect-PnPOnline -url $destination -Credentials $credential;

Apply-PnPProvisioningTemplate -path ($saveDir + "Template.xml") -Handlers Navigation, Lists, Pages, Files -ClearNavigation

The complete script is available at