I am currently trying to automatize downloading certain files in a Sharepoint-online folder by scripting in PowerShell.

At this point the script (look below) only downloads one specific file, while I want to download files based on their details (for example "Last Modified"). In other words, somehow manage to differentiate between files, so that only the newly uploaded files will be downloaded.

Hence, I wonder if anyone has a script or good tips for how to get these details for files in a folder, and also how to set restrictions on which to download.

The script I am currently working with is provided below.

#Config Variables
$SiteURL = "https://domain.sharepoint.com/sites/TeamSite1"
$FileRelativeURL = "/sites/TeamSite1/Shared Documents/PermissionRpt.csv"
$DownloadPath ="C:\temp"

#Get Credentials to connect
$Cred = Get-Credential

Try {
    #Connect to PNP Online
    Connect-PnPOnline -Url $SiteURL -Credentials $Cred

    #powershell download file from sharepoint online
    Get-PnPFile -Url $FileRelativeURL -Path $DownloadPath -AsFile
catch {
    write-host "Error: $($_.Exception.Message)" -foregroundcolor Red

2 Answers 2


You could use a CAML query to select your files. This example will get the last 5 modified files. Note that RowLimit won't work as expected, hence the select -first 5 at the end

$listname = "Documents"
$query = "<View><Query><OrderBy><FieldRef Ascending='False' Name='Modified'/></OrderBy></Query></View>"
$items = Get-PnPListItem -Query $query -List $listname | select -first 5
foreach ($item in $items) {

We can download the file from SharePoint online using the below PowerShell code - this code will download load all files from the given SharePoint online library within the given date ranges, however if you want to do the specific file inside the for each loop you need to add an if condition for the file you want to download.

#Load SharePoint CSOM Assemblies
#Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
#Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"

$fileName = "File_Downloading_Report"
#'yyyyMMddhhmm   yyyyMMdd
$enddate = (Get-Date).tostring("yyyyMMddhhmmss")
#$filename =  $enddate + '_VMReport.doc'  
$logFileName = $fileName +"_"+ $enddate+"_Log.txt"   
$invocation = (Get-Variable MyInvocation).Value  
$directoryPath = Split-Path $invocation.MyCommand.Path  

if(!(Test-Path -path $directoryPathForLog))  
            New-Item -ItemType directory -Path $directoryPathForLog
            #Write-Host "Please Provide Proper Log Path" -ForegroundColor Red   

#$logPath = $directoryPath + "\" + $logFileName 

$logPath = $directoryPathForLog + "\" + $logFileName 

$isLogFileCreated = $False 

#DLL location

$directoryPathForDLL=$directoryPath+"\"+"Dependency Files"
if(!(Test-Path -path $directoryPathForDLL))  
            New-Item -ItemType directory -Path $directoryPathForDLL
            #Write-Host "Please Provide Proper Log Path" -ForegroundColor Red   

#DLL location

Add-Type -Path $clientDLL
Add-Type -Path $clientDLLRuntime
#File Download location

$directoryPathForFileDownloadLocation=$directoryPath+"\"+"Downloaded Files"
if(!(Test-Path -path $directoryPathForFileDownloadLocation))  
            New-Item -ItemType directory -Path $directoryPathForFileDownloadLocation
            #Write-Host "Please Provide Proper Log Path" -ForegroundColor Red   

#File Download location

function Write-Log([string]$logMsg)  
        Write-Host "Creating Log File..."   
        if(!(Test-Path -path $directoryPath))  
            Write-Host "Please Provide Proper Log Path" -ForegroundColor Red   
            $script:isLogFileCreated = $True   
            Write-Host "Log File ($logFileName) Created..."   
            [string]$logMessage = [System.String]::Format("[$(Get-Date)] - {0}", $logMsg)   
            Add-Content -Path $logPath -Value $logMessage   
        [string]$logMessage = [System.String]::Format("[$(Get-Date)] - {0}", $logMsg)   
        Add-Content -Path $logPath -Value $logMessage   

#The below function will download the file from SharePoint Online library.
Function FileDownLoadFromSPOnlineLibrary()
        [Parameter(Mandatory=$true)] [string] $SPOSiteURL,
        [Parameter(Mandatory=$true)] [string] $SourceFilePath,
        [Parameter(Mandatory=$true)] [string] $TargetFilePath,
        [Parameter(Mandatory=$true)] [string] $UserName,
        [Parameter(Mandatory=$true)] [string] $Password


        $securePassword= $Password | ConvertTo-SecureString -AsPlainText -Force  
        #Setup the Context
        $ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SPOSiteURL)
        $ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $securePassword)

        #Downloading the file from SharePoint online document libray.
        $fileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($ctx,$SourceFilePath)
        $writeStream = [System.IO.File]::Open($TargetFilePath,[System.IO.FileMode]::Create)

        Write-host -f Green "File '$SourceFilePath' has been downloaded to '$TargetFilePath' successfully!"

            $ErrorMessage = $_.Exception.Message +"in Downloading File!: " +$SourceFilePath
            Write-Host $ErrorMessage -BackgroundColor Red
            Write-Log $ErrorMessage 


#Parameters value
$listName="Documents" #Document library name
$userName = "[email protected]"
$password = "YourPassWord"
$securePassword= $password | ConvertTo-SecureString -AsPlainText -Force
#$batchSize =1000
#Parameters ends here.

#Setup the Context
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteURL)
$ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($userName, $securePassword)

#Get the List
$list = $ctx.Web.Lists.GetByTitle($listName)
$emptyString = ""
#Define CAML Query to get Files from the list in batches
$Query = New-Object Microsoft.SharePoint.Client.CamlQuery

#Here in the below two line "T13:35:58Z" and "T13:36:34Z" are hard coded static value - because while we construct this camel query thru the camel query builder these values gets appended to the date value, so we need this.
#Here in the below two line "T13:35:58Z" and "T13:36:34Z" are hard coded static value - ends here.

$Query.ViewXml = "@
    <View Scope='RecursiveAll'>
            <FieldRef Name='Created' />
            <Value IncludeTimeValue='TRUE' Type='DateTime'>$startDateVar</Value>
            <FieldRef Name='Created' />
            <Value IncludeTimeValue='TRUE' Type='DateTime'>$endDateVar</Value>

$count =0
#Get List Items in Batches

    $ListItems = $List.GetItems($Query)

    #Update Postion of the ListItemCollectionPosition
    $Query.ListItemCollectionPosition = $ListItems.ListItemCollectionPosition

    If ($ListItems.Count -eq 0) 


    #Extract the each list item from the List Items collection.
    ForEach($Item in $ListItems)
          #Example to Item metadata - this can be used if we want to download based on some item metadata condition.



                #$TargetFile="C:\PowerShell\DownLoadFilesFromSPOnline\Downloaded Files\LegalDoc.docx" 

                #If we want to download the specific file type we can check the file type using the below code 

                #Calling the function "FileDownLoadFromSPOnlineLibrary"to download file
                FileDownLoadFromSPOnlineLibrary -SPOSiteURL $SiteURL -SourceFilePath $SourceFile -TargetFilePath $TargetFile -UserName $UserName -Password $Password

                $fileDownloadingMessage=$downloadItemCount.ToString()+": "+$Item.File.Name; 
                Write-Host $fileDownloadingMessage -BackgroundColor DarkGreen
                Write-Log $fileDownloadingMessage


            $ErrorMessage = $_.Exception.Message +"in: " +$Item.File.Name
            Write-Host $ErrorMessage -BackgroundColor Red
            Write-Log $ErrorMessage 


    Write-Host "============================================================="
    Write-Host $count
    Write-Host "============================================================="

}While ($Query.ListItemCollectionPosition -ne $null)

For details execution about the above script, please refer the below article :

SharePoint Online Automation – O365 – Download files from a document library using PowerShell CSOM

  • Maybe the script should be formatted to be easier to read
    – a1mery
    Commented Mar 11, 2020 at 14:57
  • 1
    Formatted, sorry didn't observer this :-)
    – SP 2022
    Commented Mar 11, 2020 at 15:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.