Copy Files to Office 365 Groups with PowerShell

Written on February 20, 2018

Office 365 Groups are a great upgrade on the traditional SharePoint Site/Shared Mailbox/Shared OneDrive folder/whatever you were previously using to share stuff. They’re a perfect candidate for migrating a department’s “network drive” (as the users would call it) to. Perhaps your HR department have S:\Human Resources, and Finance have S:\Finance. Or worse, perhaps HR have J:\ (or whatever the Service Desk person mapped it to) and Finance have X:\ (or some other drive). Groups are a great way of centralising file storage and making files accessible to approved users from wherever they happen to be.

In migrating large (several hundred GB) department file systems to Groups, after a bit of Googling and a bit of adding my own bits, I came up with the below script to allow an administrator (or even user, realistically) to copy a large volume of files to an Office 365 Group using PowerShell.

Getting Started

First, you’ll need to install the SharePoint Patterns & Practices SharePointPnP module. This can be installed using PowerShellGet on Windows 10:

Install-Package SharePointPnpPowerShellOnline

Secondly, download the script to a folder on your computer by either selecting the text and saving it, or running the PowerShell code beneath it:

param(
    [String]
    $Path, #the path to the files to be uploaded
    
    [String]
    $siteUrl, #this is the URL of the Group in the format https://contoso.sharepoint.com/sites/yourGroupName
    
    [String]
    $listName = "Shared Documents"
              #this is the path within the site to the place where you want to put the files
              #the Groups 'files' list is 'Shared Documents' which is the default
    )

Connect-PnPOnline -Url $siteUrl -UseWebLogin

$SourcePath = Get-Location

$AllFiles = Get-ChildItem $Path -Recurse -Force -ErrorAction SilentlyContinue

$filesCreated= @()

foreach ($file in $Allfiles) {

    if ($file.GetType().Name -ne "DirectoryInfo") {
    
        #$file.FullName
        $filePath = [System.IO.Path]::GetDirectoryName($file.FullName)+"\"
        $urlPath = $filepath.Replace($SourcePath,"").Replace("/","\")
        $SpoPath = $listName+$urlPath
        $FileUrl = $siteUrl + "/" + $listName + "/" + $file.FullName.Replace($pwd.ToString(),"").TrimStart("\").Replace("\","/")

        try {
            Get-PnPFile -Url $FileUrl -ErrorAction Stop | Out-Null
            # If we got here, the file exists in the target location, do nothing
        } catch { 
            # If we got here, the file doesn't exist in the target location, so let's create it
            $filesCreated+=Add-PnPFile -Path $file.FullName -Folder $SpoPath -Values @{
                Modified = $file.LastWriteTime
                Created = $file.CreationTime
            }
        }

    }

}
$files = (Invoke-RestMethod -Uri "https://api.github.com/gists/1ee513f4b0f9ebc76f0fe84d032c3cb9").files
$fileName = $files | Get-Member -Type NoteProperty | Select -First 1 -ExpandProperty Name
Set-Content -Path $filename -Value $files.$filename.content

Thirdly, run the script with the appropriate parameters:

. .\CopyFilesToOffice365Group.ps1 `
    -Path 'M:\Shared\Human Resources\'
    -SiteUrl 'https://contoso.sharepoint.com/sites/HumanResources' `
    -listName 'Shared Documents'

Done! Now it’ll run and copy your files up. Errors will need to be reviewed and remediated manually, though the PnP module does a pretty decent job of telling you what went wrong.

Caveats

  • This script (or, rather, the SharePoint Patterns & Practices module) doesn’t support moving files over 256 MB. You’ll need to move these manually based on the errors generated by this script