Introduction to Robocopy for Scheduled File Backups on Windows Server 2019
Robocopy (Robust File Copy for Windows) is a command-line tool built into Windows Server 2019 that provides enterprise-grade file copying and synchronization capabilities. It supports multi-threaded parallel copy operations, ACL (Access Control List) preservation, VSS-aware backup mode (bypassing file locks), retry on failure, incremental copy (only changed files), and comprehensive logging. When combined with Windows Task Scheduler and PowerShell scripting, Robocopy becomes a powerful scripted backup solution for file data, web content, application exports, and configuration directories. This guide covers all the essential Robocopy switches for backup use cases, building resilient backup scripts, scheduling them, and implementing rotation and verification.
Essential Robocopy Switches for Backup Operations
Understanding Robocopy’s switches is essential for configuring backups correctly. The most important switches for backup scenarios:
/E — copy all subdirectories including empty ones (essential for complete directory tree backup). /COPYALL — copy all file attributes: data (D), attributes (A), timestamps (T), NTFS ACLs/security (S), owner (O), and auditing (U). Use this when preserving permissions is required. /COPY:DAT — copy data, attributes, and timestamps only (no security/owner) — faster and used when permissions are managed centrally. /B — backup mode: the copy process requests the SeBackupPrivilege right to read files that would otherwise be inaccessible due to NTFS permissions. /ZB — try normal copy first, fall back to backup mode if access denied. /MIR — mirror mode: synchronizes the destination to match the source exactly, deleting files from the destination that no longer exist in the source. /R:n — retry count on failure (default 1,000,000 — set to 3 for reasonable retry behavior). /W:n — wait n seconds between retries. /MT:n — multi-threaded copy using n threads (default 8, up to 128). Dramatically speeds up operations on fast storage. /LOG:file — write a log to a file (overwrites). /LOG+:file — append to a log file. /NP — no progress percentage (cleaner log output for scheduled tasks). /TEE — output to console AND log file simultaneously. /XD — exclude directories. /XF — exclude files by name or pattern. /XA:H — exclude hidden files. /DCOPY:T — copy directory timestamps (useful for preserving directory modification dates). /NODCOPY — don’t copy directory attributes at all.
Basic Incremental Backup Script
The simplest Robocopy backup copies only changed files (files that are newer or have different sizes in the source vs destination), making it an efficient incremental backup:
robocopy "D:SharesFinance" "\backupserverbackupsFinance" /E /COPYALL /B /R:3 /W:10 /MT:8 /LOG+:"C:BackupLogsFinance-backup.log" /NP
This backs up the Finance share to the backup server, preserving all attributes, using 8 threads, and retrying 3 times on failure. Run this nightly and only changed files are transferred on subsequent runs, making it fast after the first full copy.
Mirror Backup with Timestamped Rotation
For a backup strategy that keeps the last N days of changes, use timestamped destination folders with a pure copy (not mirror mode) and implement rotation. The following PowerShell script creates a daily backup in a date-named folder:
# daily-backup.ps1
$Source = "D:SharesFinance"
$BackupRoot = "\backupserverbackupsFinance"
$DateStamp = Get-Date -Format "yyyyMMdd"
$Dest = Join-Path $BackupRoot $DateStamp
$LogFile = "C:BackupLogsFinance-$DateStamp.log"
$RetainDays = 30
# Run Robocopy
robocopy $Source $Dest /E /COPYALL /B /R:3 /W:10 /MT:8 /LOG:$LogFile /NP /TEE
$ExitCode = $LASTEXITCODE
if ($ExitCode -ge 8) {
# Send failure alert
Send-MailMessage -SmtpServer smtp.company.com -From [email protected] -To [email protected] -Subject "Robocopy Backup FAILED: $env:COMPUTERNAME" -Body "Exit code: $ExitCode. See log: $LogFile"
}
# Remove backup folders older than retention period
Get-ChildItem -Path $BackupRoot -Directory | Where-Object {
$_.Name -match '^d{8}$' -and
[datetime]::ParseExact($_.Name, "yyyyMMdd", $null) -lt (Get-Date).AddDays(-$RetainDays)
} | Remove-Item -Recurse -Force
Incremental Backup Using the Archive Bit
Robocopy supports archive-bit-based incremental backups. When a file is modified on Windows, the OS sets its archive attribute. Robocopy’s /A switch copies only files with the archive bit set, and /M copies those files and then clears the archive bit (marking them as backed up). This is the same mechanism used by traditional tape backup software:
robocopy "D:Shares" "\backupserverbackupsincremental" /E /COPY:DAT /B /M /R:3 /W:5 /MT:16 /LOG+:"C:BackupLogsincremental.log" /NP
Warning: /M clears the archive bit on the source, which can interfere with other backup solutions running against the same data. Use this approach only when Robocopy is the sole backup mechanism for the source data.
VSS-Aware Backup Using Volume Shadow Copy
Robocopy’s /B (backup mode) helps with permission issues but does not handle open/locked files. For a VSS-consistent backup that captures locked files (databases, Outlook PST files, etc.), use the /LFSM switch or combine Robocopy with a VSS snapshot:
# Create a VSS snapshot, mount it, copy from snapshot, then delete snapshot
$Volume = "D:"
$Shadow = (Get-WmiObject -Class Win32_ShadowCopy).Create($Volume + "", "ClientAccessible")
$ShadowID = $Shadow.ShadowID
$ShadowPath = (Get-WmiObject -Class Win32_ShadowCopy | Where-Object { $_.ID -eq $ShadowID }).DeviceObject + ""
# Mount the shadow copy
$MountPoint = "C:VSSMount"
New-Item -ItemType Directory -Path $MountPoint -Force | Out-Null
& cmd.exe /c "mklink /d $MountPoint $ShadowPath"
# Robocopy from the VSS snapshot
robocopy "$MountPointSharesFinance" "\backupserverbackupsFinance-VSS" /E /COPY:DAT /B /R:3 /W:5 /MT:8 /LOG+:"C:BackupLogsFinance-VSS.log" /NP
# Cleanup the mount and delete the snapshot
Remove-Item $MountPoint -Force
(Get-WmiObject -Class Win32_ShadowCopy | Where-Object { $_.ID -eq $ShadowID }).Delete()
Scheduling Robocopy with Task Scheduler
Register the backup script as a nightly scheduled task running as SYSTEM or a service account with access to the backup destination:
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NonInteractive -NoProfile -ExecutionPolicy Bypass -File C:BackupScriptsdaily-backup.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At "23:30"
$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Hours 6) -StartWhenAvailable -MultipleInstances IgnoreNew
Register-ScheduledTask -TaskName "Robocopy-Finance-Backup" -Action $action -Trigger $trigger -Settings $settings -User "NT AUTHORITYSYSTEM" -RunLevel Highest
Verifying Backup Completeness
Parse the Robocopy log to verify backup completeness and generate a summary report:
$log = Get-Content "C:BackupLogsFinance-20260517.log"
$summary = $log | Select-String "Files :|Dirs :|Bytes :|Speed :|Ended :"
$summary | ForEach-Object { Write-Host $_.Line }
$exitLine = $log | Select-String "ROBOCOPY"
Write-Host $exitLine
A Robocopy exit code of 0 means no files were copied (source and destination are identical — no changes). Exit code 1 means files were successfully copied. Exit codes 2–7 indicate various combinations of extra files, mismatches, and failures that do not indicate a critical problem. Exit code 8 or higher indicates a failure where at least some files were not copied. Build alerting around exit code >= 8 in your backup scripts.