In this guide, we will show you a PowerShell script that can help you copy all OneDrive files from one user to another. This is especially useful when someone leaves a company, and their files need to go to another user. This process is important to maintain the organization’s data continuity and make sure that important files remain intact. This script will copy the files, recreate the same folder structures, and take care of some common errors.
Also see: How to Check Office 365 User License Using PowerShell
Page Contents
Before you start
To make this script work, you’ll need a few things set up in PowerShell:
- The MSOnline module to manage Azure Active Directory.
- The SharePointPnPPowerShellOnline module to let you work with SharePoint Online.
- The SharePoint Online Management Shell, for managing SharePoint Online site collections.
To get the MSOnline module, type this:
Install-Module MSOnline
For the SharePointPnPPowerShellOnline module, use this command:
Install-Module SharePointPnPPowerShellOnline
And for the SharePoint Online Management Shell, do this:
- Go to the SharePoint Online Management Shell download page.
- Hit the “Download” button.
- After downloading, run the installer and follow the steps to install it.
Once you’ve got everything you need, you’re ready to run the script.
How to move OneDrive files to a new user with PowerShell
This PowerShell script automates moving all files and folders from one user’s OneDrive to another within Office 365. It’s very helpful for admins who need to handle files when someone leaves the company or just to move things around.
$departingUserEmail = Read-Host "Enter the email address of the user who is leaving"
$destinationUserEmail = Read-Host "Enter the email address of the destination user"
$adminUsername = Read-Host "Enter the username of the Global Admin account"
$adminCredentials = Get-Credential -Credential $adminUsername
Connect-MsolService -Credential $adminCredentials
$initialDomain = Get-MsolDomain | Where-Object {$_.IsInitial -eq $true}
$sharePointAdminURL = "https://$($initialDomain.Name.Split(".")[0])-admin.sharepoint.com"
$departingUserUnderscore = $departingUserEmail -replace "[^a-zA-Z]", "_"
$destinationUserUnderscore = $destinationUserEmail -replace "[^a-zA-Z]", "_"
$departingOneDriveSite = "https://$($initialDomain.Name.Split(".")[0])-my.sharepoint.com/personal/$departingUserUnderscore"
$destinationOneDriveSite = "https://$($initialDomain.Name.Split(".")[0])-my.sharepoint.com/personal/$destinationUserUnderscore"
Write-Host "`nEstablishing connection to SharePoint Online" -ForegroundColor Blue
Connect-SPOService -Url $sharePointAdminURL -Credential $adminCredentials
Write-Host "`nGranting administrative access to $adminUsername on both OneDrive site collections" -ForegroundColor Blue
Set-SPOUser -Site $departingOneDriveSite -LoginName $adminUsername -IsSiteCollectionAdmin $true
Set-SPOUser -Site $destinationOneDriveSite -LoginName $adminUsername -IsSiteCollectionAdmin $true
Write-Host "`nConnecting to $departingUserEmail's OneDrive using SharePoint Online PNP module" -ForegroundColor Blue
Connect-PnPOnline -Url $departingOneDriveSite -Credentials $adminCredentials
Write-Host "`nRetrieving display name of $departingUserEmail" -ForegroundColor Blue
$departingUser = Get-PnPSiteCollectionAdmin | Where-Object {$_.loginname -match $departingUserEmail}
if ($departingUser -contains $null) {
$departingUser = @{
Title = "Departing User"
}
}
$departingOneDrivePath = "/personal/$departingUserUnderscore/Documents"
$destinationOneDrivePath = "/personal/$destinationUserUnderscore/Documents/$($departingUser.Title)'s Files"
$destinationOneDriveSiteRelativePath = "Documents/$($departingUser.Title)'s Files"
Write-Host "`nFetching all items from $($departingUser.Title)" -ForegroundColor Blue
$items = Get-PnPListItem -List Documents -PageSize 1000
$largeItems = $items | Where-Object {[long]$_.fieldvalues.SMTotalFileStreamSize -ge 261095424 -and $_.FileSystemObjectType -contains "File"}
if ($largeItems) {
$largeExport = @()
foreach ($item in $largeItems) {
$largeExport += "$(Get-Date) - Size: $([math]::Round(($item.FieldValues.SMTotalFileStreamSize / 1MB),2)) MB Path: $($item.FieldValues.FileRef)"
Write-Host "File size exceeds limit: $($item.FieldValues.FileRef)" -ForegroundColor DarkYellow
}
$largeExport | Out-file C:\LargeFiles.txt -Append
Write-Host "A list of files exceeding the size limit from $($departingUser.Title) has been exported to C:\LargeFiles.txt" -ForegroundColor Yellow
}
$rightSizeItems = $items | Where-Object {[long]$_.fieldvalues.SMTotalFileStreamSize -lt 261095424 -or $_.FileSystemObjectType -contains "Folder"}
Write-Host "`nConnecting to $destinationUserEmail's OneDrive using SharePoint PNP PowerShell module" -ForegroundColor Blue
Connect-PnPOnline -Url $destinationOneDriveSite -Credentials $adminCredentials
Write-Host "`nFiltering items by folders" -ForegroundColor Blue
$folders = $rightSizeItems | Where-Object {$_.FileSystemObjectType -contains "Folder"}
Write-Host "`nCreating directory structure" -ForegroundColor Blue
foreach ($folder in $folders) {
$path = ('{0}{1}' -f $destinationOneDriveSiteRelativePath, $folder.fieldvalues.FileRef).Replace($departingOneDrivePath, '')
Write-Host "Creating folder in $path" -ForegroundColor Green
$newFolder = Ensure-PnPFolder -SiteRelativePath $path
}
Write-Host "`nCopying files" -ForegroundColor Blue
$files = $rightSizeItems | Where-Object {$_.FileSystemObjectType -contains "File"}
$fileErrors = ""
foreach ($file in $files) {
$destPath = ("$destinationOneDrivePath$($file.fieldvalues.FileDirRef)").Replace($departingOneDrivePath, "")
Write-Host "Copying $($file.fieldvalues.FileLeafRef) to $destPath" -ForegroundColor Green
$newFile = Copy-PnPFile -SourceUrl $file.fieldvalues.FileRef -TargetUrl $destPath -OverwriteIfAlreadyExists -Force -ErrorVariable errors -ErrorAction SilentlyContinue
$fileErrors += $errors
}
$fileErrors | Out-File C:\fileErrors.txt
Write-Host "`nRevoking administrative access for $adminUsername on OneDrive site collections" -ForegroundColor Blue
Set-SPOUser -Site $departingOneDriveSite -LoginName $adminUsername -IsSiteCollectionAdmin $false
Set-SPOUser -Site $destinationOneDriveSite -LoginName $adminUsername -IsSiteCollectionAdmin $false
Write-Host "`nProcess completed!" -ForegroundColor Green
Quick summary of the script
The following is a quick summary of what the script actually does, how it helps to move files from one person’s OneDrive to another’s in Office 365, from the top line to the bottom.
Gathering information
First off, you’ll be asked for the emails of the user leaving and the one receiving the files, plus the admin username.
Connecting to SharePoint online
Next, it uses the admin’s info to connect to Microsoft’s services and sets up the right URLs for the OneDrive sites.
Getting into the OneDrive sites
The script makes sure the admin can get into both OneDrive sites to move things around.
Finding and sorting files
Then, it jumps into the leaving user’s OneDrive, grabs all their stuff, and sorts it by size and type.
Moving the files over
After connecting to the receiving user’s OneDrive, it starts moving files and making sure everything goes in the right places.
Cleaning up
When it’s all done, it removes the admin’s access to the sites to keep everything secure.
This script can save you a lot of time if you are an admin who needs to deal with multiple OneDrive accounts, especially when someone has just left the company. Just copy the script into PowerShell, and enter the required details such as email addresses and the users you want to move from and to, and you’re good to go.
One last thing
It’s always a good idea to test the script in a safe environment, say on some OneDrive accounts that don’t matter, before using it for real tasks, just to make sure it works as you want it to and for your needs.