Archive script not working

Uggg. What am I missing here… The script is “running” but not doing anything…


SharePoint Archiving



-Calling with zero arguments will run from the root of the document library

-Use additional arguments to run from subdirectories e.g. ./ArchiveDocumentLibrary.ps1 Directory1 ChildDirectory2 GrandChildDirectory3

Note. that directories must be specified individually, in order, and with a blank space between each one


- Moves files older than $ArchiveDate out of the source location into the Archive location

- Deletes empty folders in the source location if $CleanupDirectories is set

- Files are stored under a folder with $ListName in the target list. In this way, you can archive multiple source lists to the same archive location so long as they have different names.

Note. Be wary of common list names like “Shared Documents”. You will want to ensure these are backed up to different target lists or else you could get in a mess.

- Liable to throttling by Microsoft so be patient, it will get there in the end!

Required Module for the script. Uncomment to install this module if you don’t have it already

Install-Module -Name PnP.PowerShell


Root Site Url

$SiteUrl = “
$username = “username”
$password = “password”

Source Settings

$RelativeUrl = “/sites/name”
$ListName = “Shared Documents”

Archive Settings

$ArchiveRelativeUrl = “/sites/Archive”
$ArchiveListName = “Shared Documents”

Job Settings

$ArchiveDate = Get-Date “2022-01-01” # Anything older than this will be archived
$FileLimit = -1 # Limits the number of files processed at a time (useful for testing). use -1 to turn this off
$CleanupDirectories = $true # Whether to remove empty directories or not
$Debug = $false # For debugging / dry runs. Enables additional output and doesn’t actually change anything in the source library


function Recurse-Files($Folder, $Stack)
$items = Get-PnPFolderItem -FolderSiteRelativeUrl $Folder
if ($Debug -eq $true)
Write-Output ("Folder: " + $Folder)
Write-Output ("Count: " + $items.count)

foreach ($item in $items)
    if ($Debug -eq $true)
        Write-Output ("Item: " + $item.Name)

    if ($item.Name -eq "Forms") { continue }
    if ($item.Name -eq "_catalogs") { continue }

    if ($item.TypedObject.ToString() -ne 'Microsoft.SharePoint.Client.Folder')
        $file = Get-PnPFile -AsListItem -Url $item.ServerRelativeUrl
        if ((Get-Date $file.FieldValues.Modified) -lt $ArchiveDate)
            Archive-File $item $file $Folder $Stack
            $FileLimit = $FileLimit - 1
            if ($FileLimit -eq 0) { Exit }
        $NewPath = ($Folder + "/" + $item.Name)

        $TempStack = $Stack.PSObject.Copy()

        Recurse-Files $NewPath $TempStack

if ($CleanupDirectories)
    $items = Get-PnPFolderItem -FolderSiteRelativeUrl $Folder
    if ($items.count -gt 0) {} else {
        Cleanup-Empty-Folder $Stack


function Archive-File($Item, $FileItem, $ParentFolder, $Stack)
Write-Output ("Archiving: " + $Item.Name + " - " + $FileItem.FieldValues.Modified)

# Build Destination Path
$TargetUrl = "/$ArchiveListName"

# Generate Destination Folder if it doesn't exist
if ($Debug -eq $false)
    $folders = $Stack.ToArray() | ForEach-Object { $_.ToString() }
    $TargetUrl = ($TargetUrl + "/" + ($folders -join "/"))
    Resolve-PnPFolder -SiteRelativePath $TargetUrl -Connection $ArchiveConnection | Out-Null

# Move the File to Archive
if ($Debug -eq $false)
    $SourceUrl = ($RelativeUrl + "/" + $ParentFolder + "/" + $Item.Name)
    $TargetUrl = ($ArchiveRelativeUrl + $TargetUrl + "/" + $Item.Name)
    Move-PnPFile -SourceUrl $SourceUrl -TargetUrl $TargetUrl -Overwrite -AllowSchemaMismatch -IgnoreVersionHistory -Force


function Cleanup-Empty-Folder($Stack)
$temps = $Stack.PSObject.Copy()

$Name = $temps.Pop()

$TargetUrl = ""
while ($temps.count -gt 1) { $TargetUrl = ("/" + $temps.Pop() + $TargetUrl) }
$TargetUrl = ($ListName + $TargetUrl)

Write-Output ("Clean-up: " + $Name + " in " + $TargetUrl)
if ($Debug -eq $false)
    Remove-PnPFolder -Name $Name -Folder $TargetUrl -Force


$encpassword = ConvertTo-SecureString $password -AsPlainText -Force
$credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $encpassword

Get Connection for connecting to the archive (need to do this before the other connection as it also connects interactive)

$ArchiveConnection = Connect-PnPOnline -Url ($SiteUrl + $ArchiveRelativeUrl) -ReturnConnection -UseWebLogin

Initial Connection to SharePoint Online

Connect-PnPOnline -Url ($SiteUrl + $RelativeUrl) -Credentials $credentials

Prep stack

$StartStack = New-Object System.Collections.Stack

Load Path from args

$StartPath = $ListName
for ($i = 0; $i -lt $args.count; $i++)
$StartPath = ($StartPath + “/” + $args[$i])

if ($Debug -eq $true) { Get-PnPList }


Recurse-Files $StartPath $StartStack

Welcome to the forum. :wave:t3:

Could you please do us a favor and edit your question again and fix the formatting?

When you post code, sample data, console output or error messages please format it as code using the preformatted text button ( </> ). Simply place your cursor on an empty line, click the button and paste your code.

Thanks in advance

How to format code in 1 <---- Click :point_up_2:t4: :wink:

( !! Sometimes the preformatted text button hides behind the settings gear symbol. :wink: )

Regardless of that - you shared a lot of code but you don’t explain what the actual issue is.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.