How to make list of local OneDrive files that haven't finished sync'ing

Herrick Andrews 5 Reputation points
2025-12-02T11:45:51.03+00:00

How can I search my local OneDrive folder to produce a list of all files that haven't completed sync'ing? I can write code in VBA if that's what it takes

Microsoft 365 and Office | OneDrive | Other | Windows
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Francisco Montilla 24,280 Reputation points Independent Advisor
    2025-12-02T12:24:33.4033333+00:00

    Hello,

    The way is to read the OneDrive Status column that File Explorer exposes for each item, then filter anything that is syncing, pending, paused, or in error.

    You can do this entirely locally with PowerShell using the built in Shell COM interface. The script below finds your OneDrive folder or folders, walks all files, reads the Explorer Status text for each file, and writes a CSV list of the ones that are not fully synced.

    Paste this into Windows PowerShell, press Enter, and wait for the CSV to appear on your Desktop:

    $ErrorActionPreference = 'SilentlyContinue'
    
    function Get-OneDriveRoots {
      $roots = New-Object System.Collections.Generic.HashSet[string]
      foreach ($name in 'OneDrive','OneDriveCommercial','OneDriveConsumer') {
        $p = [Environment]::GetEnvironmentVariable($name, 'User')
        if ($p -and (Test-Path $p)) { $roots.Add((Get-Item $p).FullName) | Out-Null }
      }
      $regPath = 'HKCU:\Software\Microsoft\OneDrive\Accounts'
      if (Test-Path $regPath) {
        Get-ChildItem $regPath | ForEach-Object {
          $uf = (Get-ItemProperty $_.PsPath -Name 'UserFolder' -ErrorAction SilentlyContinue).UserFolder
          if ($uf -and (Test-Path $uf)) { $roots.Add((Get-Item $uf).FullName) | Out-Null }
        }
      }
      return $roots.ToArray()
    }
    
    $shell = New-Object -ComObject Shell.Application
    $StatusHeader = 'Status'   # If your Windows is not in English, change this to the localized column name
    
    $indexCache = @{}
    
    function Get-StatusIndex([string]$folder) {
      if ($indexCache.ContainsKey($folder)) { return $indexCache[$folder] }
      $ns = $shell.NameSpace($folder)
      if (!$ns) { $indexCache[$folder] = -1 ; return -1 }
      $idx = -1
      for ($i=0; $i -lt 500; $i++) {
        $h = $ns.GetDetailsOf($null, $i)
        if ([string]::IsNullOrWhiteSpace($h)) { continue }
        if ($h -eq $StatusHeader -or $h -eq 'Sync Status') { $idx = $i ; break }
      }
      $indexCache[$folder] = $idx
      return $idx
    }
    
    function Get-ItemStatus([string]$path) {
      $folder = Split-Path -LiteralPath $path -Parent
      $name = Split-Path -LiteralPath $path -Leaf
      $ns = $shell.NameSpace($folder)
      if (!$ns) { return $null }
      $idx = Get-StatusIndex $folder
      if ($idx -lt 0) { return $null }
      $item = $ns.ParseName($name)
      if (!$item) { return $null }
      return $ns.GetDetailsOf($item, $idx)
    }
    
    $roots = Get-OneDriveRoots
    if (-not $roots -or $roots.Count -eq 0) { Write-Error 'No OneDrive folders found' ; return }
    
    # Match any status text that indicates not fully synced. Tweak if you want to be stricter.
    $pattern = '(sync|pending|problem|error|conflict|paused|processing)'
    
    $results = New-Object System.Collections.Generic.List[object]
    
    foreach ($root in $roots) {
      Get-ChildItem -LiteralPath $root -File -Recurse -Force | ForEach-Object {
        $st = Get-ItemStatus $_.FullName
        if ($st -and ($st -match $pattern -and $st -notmatch 'up to date')) {
          $results.Add([pscustomobject]@{ Path = $_.FullName ; Status = $st })
        }
      }
    }
    
    $csv = Join-Path ([Environment]::GetFolderPath('Desktop')) ("OneDrive_NotSynced_{0:yyyyMMdd_HHmmss}.csv" -f (Get-Date))
    $results | Sort-Object Path | Export-Csv -Path $csv -NoTypeInformation -Encoding UTF8
    
    Write-Host "Items not fully synced: $($results.Count)"
    Write-Host "Saved to: $csv"
    

    If your Windows is localized and the Explorer column is not named Status, set the $StatusHeader variable to the exact column caption you see in File Explorer. If you only want items that are strictly in Sync pending, change the $pattern to sync pending.

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.