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

Comments/questions

There's no commenting functionality here. If you'd like to comment, please either mention me (@chris@aus.social) on Mastodon or email me. I don't have any logging or analytics running on this website, so if you found something useful or interesting it would mean a lot to hear from you.