OneDrive Document download using Powershell

The best way to downloading all documents from OneDrive is to sync on local machine using OneDrive Sync client. But there could be scenarios where you need to get all data of another user, you cannot connect multiple accounts OneDrive Sync client and, in that scenario, you can use PowerShell script to download all content for a user.

I have written a PowerShell script using PnP PowerShell cmdlets which is very helpful to download all documents for a user.

###########################################################################
#Author: Adnan Amin
#blog: Https://mstechtalk.com
#Downloading files from OneDrive to local machine
###########################################################################

$webUrl = "https://mstalk-my.sharepoint.com/personal/<user>_mstechtalk_com";
$listUrl = "Documents";
$destination = "F:\test"

#Connect-PnPOnline -Url $webUrl 
Connect-PnPOnline -Url $webUrl -UseWebLogin;
$web = Get-PnPWeb
$list = Get-PNPList -Identity $listUrl

function ProcessFolder($folderUrl, $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]
        Write-Host "Copying file " $file.Name " at " $destinationfolder
        Get-PnPFile -ServerRelativeUrl $file.ServerRelativeUrl -Path $destinationfolder -FileName $file.Name -AsFile
    }
}

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
            write-host "Processing folder: " $folder.Name " .. at " $currentPath
            ProcessSubFolders $tempfolders $targetFolder
        }
    }
}

ProcessFolder $listUrl $destination + "\" 
#Write-Host "listUrl: " $listUrl

#Download files in folders
$tempfolders = Get-PnPProperty -ClientObject $list.RootFolder -Property Folders
Write-Host "tempfolders: " $tempfolders
ProcessSubFolders $tempfolders $destination + "\"

Download could take time as it all depends upon the number of documents. If job get stuck or stopped due to some error, I would recommend you to download files in chunks by passing the URLs of OneDrive folders instead of full OneDrive path, you need to run the script multiple times but this will minimize the number of errors.

Adnan is six time Microsoft MVP (Since 2015) with over 16 years of extensive experience with major expertise on SharePoint, SharePoint based development, Microsoft 365, Microsoft Teams, .Net Platform and Microsoft BI. He is currently working Sr Microsoft Consultant at Olive + Goose. He is MCT Regional Lead for Pakistan Chapter since 2012. He is working on SharePoint for past 12 years and worked on different intranet/intranet solutions for private & govt. sector majorly in United states and Gulf region and have experience of working with multiple Fortune 500 companies. He is a trainer, technology evangelist and also speaks in community forums.

Leave a Reply