cheat sheet
xcopy
Copy files and directory trees with attribute preservation, date filtering, exclusion lists, and verification. The step between copy and robocopy for most scripting needs.
xcopy — Extended Copy
What it is
xcopy is a Windows command-line tool that extends the basic copy command with support for recursive directory trees, attribute filtering, date-based filtering, exclusion lists, and attribute preservation. It has shipped with every Windows version since DOS 3.3 and is found at C:\Windows\System32\xcopy.exe. For production-grade replication, mirroring, or network-resilient copies, prefer robocopy — but xcopy remains useful for simple recursive and attribute-aware copies without the complexity of robocopy's 80+ flags.
Availability
xcopy ships with all Windows versions as C:\Windows\System32\xcopy.exe. Run from an elevated prompt when copying protected system files or UNC paths that require administrative access.
xcopy /?
Output:
Copies files and directory trees.
XCOPY source [destination] [/A | /M] [/D[:date]] [/P] [/S [/E]] [/V] [/W]
[/C] [/I] [/Q] [/F] [/L] [/G] [/H] [/R] [/T]
[/U] [/K] [/N] [/O] [/X] [/Y | /-Y] [/Z]
[/B] [/J] [/EXCLUDE:file1[+file2][+file3]...]
Syntax
Source is a file, wildcard, or directory path. Destination defaults to the current directory. Key flags control whether the copy is recursive (/S), preserves attributes (/K), and handles conflicts (/Y).
xcopy source [destination] [switches]
Output: (shows count of files copied, or error)
Essential options
| Switch | Meaning |
|---|---|
/S | Copy directories and subdirectories (except empty ones) |
/E | Copy all subdirectories including empty ones (use with /S) |
/I | If destination doesn't exist, assume it's a directory |
/Y | Overwrite existing files without prompting |
/-Y | Prompt before overwriting |
/H | Copy hidden and system files |
/R | Overwrite read-only destination files |
/K | Preserve file attributes (default strips read-only) |
/O | Preserve ownership and ACL information |
/A | Copy only files with archive bit set |
/M | Same as /A but clears archive bit after copying |
/D:m-d-y | Copy only files modified on or after the specified date |
/D (no date) | Copy only files newer than the destination |
/P | Prompt before creating each destination file |
/F | Display full source and destination paths during copy |
/Q | Quiet — do not display file names during copy |
/L | List files that would be copied (dry run) |
/C | Continue copying even if errors occur |
/T | Create destination directory tree but copy no files |
/U | Copy only files that already exist in destination |
/EXCLUDE:file | Exclude files matching strings listed in the file |
/Z | Copy in restartable mode (network resilience) |
/B | Copy symbolic links themselves, not their targets |
Recursive directory copy
/S makes xcopy descend into subdirectories; add /E to also recreate empty subdirectories. Without /I, xcopy may prompt whether the destination is a file or directory — always add /I when the destination doesn't yet exist.
rem Copy a folder tree to a new location
xcopy C:\Projects\myapp D:\Backup\myapp /S /E /I /Y
Output:
C:\Projects\myapp\main.py
C:\Projects\myapp\utils.py
C:\Projects\myapp\tests\test_main.py
3 File(s) copied
rem Only copy non-empty directories
xcopy C:\Logs D:\Archive\Logs /S /I /Y
Output:
C:\Logs\app.log
C:\Logs\error.log
2 File(s) copied
Preserving attributes
By default xcopy strips the read-only bit from copied files. /K preserves all original attributes. /O also preserves NTFS ownership and ACLs (requires appropriate permissions).
xcopy C:\Source D:\Dest /S /E /I /K /Y
Output:
4 File(s) copied
rem Preserve ACLs (requires elevation)
xcopy C:\Source D:\Dest /S /E /I /K /O /Y
Output:
4 File(s) copied
Incremental copies with archive bit
/A copies only files with the archive attribute set (files modified since last backup). /M does the same but clears the archive bit afterward — marking files as "backed up".
rem Incremental: copy only changed files
xcopy C:\Work D:\DailyBackup /S /E /I /M /Y
Output:
C:\Work\report.docx
1 File(s) copied
rem Cumulative: copy changed files, leave archive bit set
xcopy C:\Work D:\WeeklyBackup /S /E /I /A /Y
Output:
C:\Work\report.docx
C:\Work\notes.txt
2 File(s) copied
Date-filtered copies
/D without a date copies only files newer than their destination counterpart. /D:m-d-y copies only files modified on or after the given date.
rem Copy only files newer than destination (sync-style)
xcopy C:\Source D:\Dest /S /D /Y
Output:
C:\Source\updated_report.docx
1 File(s) copied
rem Copy only files modified on or after 01 April 2026
xcopy C:\Logs D:\Archive /S /D:4-1-2026 /Y
Output:
C:\Logs\app.log
C:\Logs\error.log
2 File(s) copied
Exclusion lists
/EXCLUDE:filename reads exclusion strings from a text file — one string per line. Any source file whose full path contains that string is skipped.
rem Create an exclusion list
echo .git\ > exclude.txt
echo node_modules\ >> exclude.txt
echo __pycache__\ >> exclude.txt
rem Copy excluding those paths
xcopy C:\Projects\myapp D:\Deploy\myapp /S /E /I /Y /EXCLUDE:exclude.txt
Output:
C:\Projects\myapp\main.py
C:\Projects\myapp\utils.py
2 File(s) copied
Dry run
/L lists the files that would be copied without actually copying them — useful for verifying a command before committing.
xcopy C:\Projects\myapp D:\Backup\myapp /S /E /I /L
Output:
C:\Projects\myapp\main.py
C:\Projects\myapp\utils.py
C:\Projects\myapp\tests\test_main.py
3 File(s) would be copied
Common pitfalls
/Swithout/Eskips empty directories — always add/Eif the directory structure matters.- Destination ambiguity prompt — without
/I,xcopyasks "is destination a file or directory?" Use/Iwhen the destination directory doesn't yet exist. - Read-only files at destination —
xcopyfails on read-only destinations unless you pass/Rto force overwrite. - Exit codes are not just 0/1 —
xcopyreturns 0 (ok), 1 (no files matched), 2 (user pressed Ctrl+C), 4 (init error), or 5 (disk write error). Check%ERRORLEVEL%in scripts. - Paths over 260 characters —
xcopydoes not support extended-length paths; userobocopyfor deep trees. - ACL preservation requires elevation —
/Osilently skips ACL copy if the process lacksSeBackupPrivilege.
Real-world recipes
Mirror a project folder for deployment
echo .git\ > xcopy_exclude.txt
echo __pycache__\ >> xcopy_exclude.txt
echo .env >> xcopy_exclude.txt
xcopy C:\Projects\myapp D:\Deploy\myapp /S /E /I /K /Y /EXCLUDE:xcopy_exclude.txt
Output:
C:\Projects\myapp\main.py
C:\Projects\myapp\utils.py
4 File(s) copied
Nightly incremental backup script
@echo off
set SRC=C:\Users\alicedev\Documents
set DST=D:\Backups\Documents
xcopy %SRC% %DST% /S /E /M /I /Y /C
echo Backup complete. Exit code: %ERRORLEVEL%
Output:
C:\Users\alicedev\Documents\report.docx
1 File(s) copied
Backup complete. Exit code: 0
Copy only files newer than destination to sync two folders
xcopy C:\Source D:\Mirror /S /D /Y /C /Q
Output:
2 File(s) copied
Create a skeleton directory tree without files
xcopy C:\Projects\myapp D:\NewProject /T /E
Output:
0 File(s) copied
Complete switch reference
xcopy accepts more than 30 switches. The table in the Essential options section above covers the everyday set; the rest are listed here for completeness.
| Switch | Meaning |
|---|---|
/A | Copy only files with archive attribute (leave bit set) |
/M | Copy only files with archive attribute and clear bit |
/D[:m-d-y] | Date filter — newer than destination, or newer than given date |
/P | Prompt for each file |
/S | Recursive, skip empty directories |
/E | Recursive, include empty directories |
/V | Verify each file as it is written (slow; mostly obsolete on NTFS) |
/W | Pause before starting (legacy "swap floppy" prompt) |
/C | Continue on error |
/I | Treat destination as directory when ambiguous |
/Q | Quiet — suppress per-file output |
/F | Verbose — full source and destination paths per file |
/L | List only — dry run |
/G | Allow copy of encrypted files to a non-EFS destination (decrypts) |
/H | Include hidden and system files |
/R | Overwrite read-only destination files |
/T | Tree only — create directory structure, copy no files |
/U | Update — only copy files that already exist at destination |
/K | Preserve attributes (read-only is kept) |
/N | Copy using generated short filenames (8.3) |
/O | Copy file ownership and ACLs |
/X | Copy file audit settings and SACL (implies /O) |
/Y | Suppress overwrite prompt |
/-Y | Force overwrite prompt (override COPYCMD=/Y) |
/Z | Restartable mode for network sources |
/B | Copy the symbolic link itself, not its target |
/J | Copy using unbuffered I/O (large files, Win8+) |
/COMPRESS | Request SMB network compression during transfer (Windows 11 / Server 2022+) |
/SPARSE | Preserve sparse-file state on copy (default) |
/-SPARSE | Disable sparse preservation; fully allocate destination file |
/NOCLONE | Skip block-cloning optimisation on ReFS / NTFS clone-aware copies |
/EXCLUDE:file[+file2] | Substring exclusion list from one or more files |
The /V (verify) switch was meaningful on the floppy era but is largely redundant on modern NTFS — the filesystem already verifies writes through its journal. Leaving it off saves time. The /W switch is purely historical.
Unbuffered I/O (/J)
/J was added in Windows 8 to bypass the Windows file cache for very large file transfers. With /J, xcopy reads and writes directly to the disk, avoiding the cache thrash that copying multi-gigabyte files normally causes. The trade-off is that small files become slightly slower because they no longer benefit from coalesced cache writes.
rem Use /J for ISO files, VM images, video archives
xcopy C:\VMs\bigimage.vhdx D:\Backup\VMs\ /J /Y
Output:
C:\VMs\bigimage.vhdx
1 File(s) copied
Rule of thumb: use /J for files larger than the RAM cache (typically 1 GB+). Skip it for trees of small text files.
Encrypted files (/G)
/G permits xcopy to read an EFS-encrypted source file and write a plaintext copy to a destination volume that does not support EFS (FAT32, exFAT, network shares). Without /G, the copy fails with "EFS encrypted, cannot copy to unencrypted volume".
rem Copy an EFS-encrypted file to a USB FAT32 stick (decrypted on arrival)
xcopy C:\Secrets\plans.docx F:\Backup\ /G /Y
Output:
C:\Secrets\plans.docx
1 File(s) copied
[!WARN]
/Gdecrypts the file at the destination. The copied file is plaintext and no longer protected by the source's EFS key. Only use/Gwhen you accept that loss of confidentiality.
Ownership and ACL preservation (/O and /X)
/O copies the file's NTFS owner and DACL (the user-facing permissions). /X extends this with the SACL — the audit policy that triggers Security event-log entries on access. Both require the process to hold SeBackupPrivilege (read source ACLs) and SeRestorePrivilege (write destination ACLs); these are granted to the Administrators group, which means you must launch cmd.exe with "Run as administrator".
rem Preserve DACL only
xcopy C:\Source D:\Dest /S /E /I /K /O /Y
rem Preserve DACL + SACL (audit policy)
xcopy C:\Source D:\Dest /S /E /I /K /X /Y
Output:
3 File(s) copied
Without elevation, xcopy silently strips ACLs and re-applies the destination folder's inherited permissions to every copied file — usually not what you want for a backup.
Restartable mode (/Z)
/Z enables network-resilient mode: if the source connection drops mid-file, xcopy retries from the last successfully-written byte rather than restarting the file from zero. It also displays a percentage indicator during transfer.
xcopy \\myhost\share\bigfile.zip D:\Backup\ /Z /Y
Output:
\\myhost\share\bigfile.zip
0%
25%
50%
75%
100%
1 File(s) copied
/Z has no effect on local-to-local copies and adds overhead on flaky connections. For production network sync, prefer robocopy /Z (which is the same flag with much richer retry and logging).
Exit codes
xcopy follows the cmd.exe convention of a numeric exit code stored in %ERRORLEVEL%. Scripts must check this to distinguish real failures from "nothing to do".
| Code | Meaning |
|---|---|
0 | Files copied without error |
1 | No files were found to copy |
2 | User pressed Ctrl+C |
4 | Initialisation error — out of memory, invalid syntax, source path not found |
5 | Disk write error |
@echo off
xcopy C:\Source D:\Dest /S /E /I /K /Y
if %ERRORLEVEL% EQU 0 echo OK: files copied
if %ERRORLEVEL% EQU 1 echo INFO: no files found
if %ERRORLEVEL% EQU 2 echo USER: aborted
if %ERRORLEVEL% GEQ 4 echo ERROR: code %ERRORLEVEL%
Output:
OK: files copied
# PowerShell — same logic
& xcopy C:\Source D:\Dest /S /E /I /K /Y
switch ($LASTEXITCODE) {
0 { 'OK' }
1 { 'No files' }
2 { 'User aborted' }
default { "ERROR: $LASTEXITCODE" }
}
Output: (one line)
xcopy vs robocopy
robocopy (introduced in the Windows Vista Resource Kit, in-box from Windows 7 onward) is the modern replacement for xcopy. Every feature that xcopy offers, robocopy does too — usually with finer control and structured output. The only reason to reach for xcopy today is when you specifically need its terse output format in a legacy batch script, or when you want a one-line invocation without robocopy's verbose header.
| Feature | xcopy | robocopy |
|---|---|---|
| Recursive copy | /S /E | /E |
| Empty dirs | /E (with /S) | included in /E |
| Multi-threaded | no | /MT[:n] (default 8, max 128) |
| Mirror mode (delete extras) | no | /MIR |
| Auto-retry | no | /R:n /W:n (default 1,000,000 × 30 s) |
| Network restart | /Z (per-file only) | /Z (per-file) and /ZB (backup mode fallback) |
| Date filter | /D:m-d-y only ≥ | /MAXAGE /MINAGE (both directions) |
| Size filter | no | /MAXSIZE /MINSIZE |
| Exclude files | /EXCLUDE:file (substring) | /XF pattern (glob) |
| Exclude dirs | no (must use exclusion file) | /XD pattern |
| ACL copy | /O /X (requires elevation) | /COPY:DATSOU /COPYALL |
| Long paths (> 260) | no | yes (default) |
| Structured log | no | /LOG /LOG+ /TEE /NFL /NDL /NJH /NJS |
| Exit codes | 0–5 (simple) | bitmask (0–16) |
| Move semantics | no | /MOVE (delete source after copy) |
| Backup-API access | no | /B /ZB (uses backup privilege) |
Equivalent recipes
The same job written with each tool, side by side:
Recursive backup, preserve attributes, overwrite:
rem xcopy
xcopy C:\Projects D:\Backup\Projects /S /E /I /K /H /Y
rem robocopy
robocopy C:\Projects D:\Backup\Projects /E /COPY:DAT /R:3 /W:5
Output:
C:\Projects\app\main.py
C:\Projects\app\utils.py
C:\Projects\README.md
...
247 File(s) copied
Incremental — changed files only:
rem xcopy — uses archive bit
xcopy C:\Work D:\DailyBackup /S /E /I /M /Y
rem robocopy — compares size and timestamp (more robust)
robocopy C:\Work D:\DailyBackup /E /XO /R:3 /W:5
Output:
C:\Work\notes\monday.md
C:\Work\reports\Q2.xlsx
2 File(s) copied
Mirror (delete destination extras):
rem xcopy — NOT POSSIBLE; xcopy never deletes at destination
rem robocopy
robocopy C:\Source D:\Mirror /MIR /R:3 /W:5
Output:
ROBOCOPY :: Robust File Copy for Windows
-------------------------------------------------------------------------------
Source : C:\Source\
Dest : D:\Mirror\
Total Copied Skipped Mismatch FAILED Extras
Files : 42 38 0 0 0 4
Network share with retry:
rem xcopy
xcopy C:\Data \\myhost\share\Data /S /E /I /Z /C /Y
rem robocopy
robocopy C:\Data \\myhost\share\Data /E /Z /R:5 /W:10 /MT:8
Output:
C:\Data\Q2.xlsx
C:\Data\contracts\acme.pdf
...
58 File(s) copied
When to keep using xcopy:
- One-shot ad-hoc copies in interactive cmd.
- Legacy batch scripts where you don't want to touch the existing logic.
- Cases where
robocopy's verbose header pollutes the output you want to capture.
When to switch to robocopy:
- Any nightly or scheduled backup.
- Mirror operations (deletion of destination extras).
- Network share copies of more than a few files.
- Trees with paths longer than 260 characters.
- Anywhere you need structured log files for audit.
See the robocopy.md page in this section for the full deep dive.
PowerShell equivalents
PowerShell ships with Copy-Item, which covers nearly every xcopy use case in a more composable way. Copy-Item accepts pipeline input, supports -Filter and -Exclude globs, preserves attributes by default, and integrates with PowerShell's standard error handling.
# Basic recursive copy
Copy-Item -Path C:\Source -Destination D:\Dest -Recurse -Force
Output: (none)
# Include hidden and system files (Force already does this)
Copy-Item -Path C:\Source\* -Destination D:\Dest -Recurse -Force
Output: (none)
# Exclude patterns (glob, multiple)
Copy-Item -Path C:\Projects\myapp\* `
-Destination D:\Deploy\myapp `
-Recurse `
-Force `
-Exclude '*.pyc', '*.log', '.env', '.git'
Output: (none)
# Filter by extension (single glob only)
Copy-Item -Path C:\Source -Destination D:\Dest -Recurse -Filter '*.docx'
Output: (none)
# Date-filtered copy — files modified in the last 24 hours
Get-ChildItem C:\Source -Recurse -File |
Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-1) } |
ForEach-Object {
$dest = $_.FullName -replace [regex]::Escape('C:\Source'), 'D:\Dest'
New-Item -ItemType Directory -Force -Path (Split-Path $dest) | Out-Null
Copy-Item -Path $_.FullName -Destination $dest -Force
}
Output: (none)
# Dry run — list what would be copied
Copy-Item -Path C:\Source -Destination D:\Dest -Recurse -WhatIf
Output:
What if: Performing the operation "Copy File" on target "Item: C:\Source\a.txt Destination: D:\Dest\a.txt".
What if: Performing the operation "Copy File" on target "Item: C:\Source\b.txt Destination: D:\Dest\b.txt".
Why prefer PowerShell
-WhatIfis more reliable thanxcopy /Lfor dry runs.-Filteruses real PowerShell globs;xcopy's/EXCLUDEmatches substrings of full paths and surprises users.- Errors surface as terminating exceptions you can
try/catch, rather than just%ERRORLEVEL%codes. Copy-Itemworks over PSDrive paths (FTP, SFTP, registry) without extra tooling.
When PowerShell falls short
Copy-Item does not handle interrupted network transfers — there is no /Z equivalent. It also does not parallelise (until you wrap it in ForEach-Object -Parallel). For nightly backups over the network, robocopy is still the right tool; for everything else inside PowerShell scripts, Copy-Item is the cleaner choice.
Exclusion file syntax (/EXCLUDE)
/EXCLUDE:filename reads a list of strings from one or more files (separated by + if multiple). Each line is a substring — xcopy skips a file whenever any exclusion string appears anywhere in the file's full path. This is a powerful but easily misused feature.
rem exclude.txt — substring matches, not globs
.git\
node_modules\
__pycache__\
.env
.pyc
Output of run:
xcopy C:\Projects\myapp D:\Deploy\myapp /S /E /I /Y /EXCLUDE:exclude.txt
| Source path | Matched substring | Copied? |
|---|---|---|
C:\Projects\myapp\.git\HEAD | .git\ | no |
C:\Projects\myapp\src\app.py | (none) | yes |
C:\Projects\myapp\src\__pycache__\app.cpython-312.pyc | __pycache__\ AND .pyc | no |
C:\Projects\myapp\.gitignore | .git (substring of .gitignore if you wrote .git) | depends |
The last row is the trap: writing .git (without trailing backslash) also excludes .gitignore, .github\, and any file with .git anywhere in the path. Always include trailing backslash for directory exclusions and a leading dot for extension exclusions.
rem Multiple exclusion files combined
xcopy C:\Src D:\Dst /S /E /I /Y /EXCLUDE:base-exclude.txt+dev-exclude.txt+local-exclude.txt
Output: (per-file output of copies)
Long paths and the 260-character limit
xcopy has historically been limited to paths shorter than 260 characters (the legacy MAX_PATH constant). Files with longer paths are skipped with "The system cannot find the path specified" or "File name too long". Unlike attrib and robocopy, xcopy does not natively understand the \\?\ extended-length prefix even on systems with LongPathsEnabled set.
rem Long path — fails
xcopy "C:\verylongproject\src\components\NavigationDrawer\subdir\deeplynested\very\long\file.txt" D:\Dest\ /I /Y
Output:
File creation error - The system cannot find the path specified.
For deep trees, prefer robocopy, which supports long paths transparently:
robocopy "C:\verylongproject" "D:\Dest" *.txt /S /R:3 /W:5
Output: (success)
Symbolic links and junctions (/B)
The default xcopy behaviour for a symbolic link is to follow it — the link's target gets copied to the destination, and the link itself disappears. /B reverses this: xcopy copies the link itself as a new symbolic link at the destination, preserving the indirection. Junction copies follow the same rule.
rem Create a symlink for testing
mklink C:\Link\report.lnk C:\Data\report.docx
rem Default — copies the target file (no longer a link at destination)
xcopy C:\Link\report.lnk D:\Backup\ /Y
rem /B — copies the link itself
xcopy C:\Link\report.lnk D:\Backup\ /B /Y
Output (default): the destination receives a real file.
Output (/B): the destination receives a symlink pointing to C:\Data\report.docx.
This matters for backup scripts: copying a follow-target by default can balloon a backup if the same target is reached through many symlinks. Use /B to preserve the symlink structure.
Environment variables that affect xcopy
xcopy honours one notable environment variable.
| Variable | Effect |
|---|---|
COPYCMD | Default overwrite behaviour — set to /Y to suppress prompt globally; /-Y overrides per-call |
rem Set COPYCMD in a session so xcopy never prompts to overwrite
set COPYCMD=/Y
xcopy C:\Source D:\Dest /S /E /I
rem Restore prompt for one call
xcopy C:\Source D:\Dest /S /E /I /-Y
Output: (no prompts, then prompted for confirmation)
Modern transport switches — /COMPRESS, /SPARSE, /NOCLONE
Microsoft has back-ported a small set of robocopy-style transport switches into xcopy on Windows 11 and Windows Server 2022 onward. These exist mostly so legacy scripts keep working over modern SMB and ReFS, even though robocopy remains the recommended tool.
| Switch | What it does | When to use |
|---|---|---|
/COMPRESS | Requests SMB Compression during the transfer when both peers support it (SMB 3.1.1, Windows 11 / Server 2022+) | Slow WAN links carrying compressible content (logs, source, plain-text data) |
/SPARSE / /-SPARSE | Preserve (default) or disable preservation of the source's sparse-file extents | /-SPARSE when destination filesystem doesn't understand sparse (FAT32, exFAT) |
/NOCLONE | Opt out of block-clone optimisation when source and destination share a clone-aware volume | Benchmarking, or when you specifically need bytes on different physical blocks |
rem Compressed copy over SMB to a remote share
xcopy C:\Reports \\fileserver01\Backup\Reports /S /E /I /K /Y /COMPRESS
Output:
C:\Reports\monthly.xlsx
C:\Reports\summary.pdf
2 File(s) copied
rem Force a fully-allocated destination (no sparse holes) when copying VHDX to a USB stick
xcopy C:\VMs\test.vhdx F:\Backup\ /Y /-SPARSE
Output:
C:\VMs\test.vhdx
1 File(s) copied
rem Disable block cloning to measure raw throughput on ReFS
xcopy D:\Data E:\Mirror /S /E /I /Y /NOCLONE
Output:
D:\Data\index.dat
... (many lines)
1247 File(s) copied
For nightly backup jobs, robocopy /COMPRESS /SPARSE:Y is still the better choice — same primitives, plus retry, multi-threading, and structured logs. Use the xcopy equivalents only when an existing batch script already calls xcopy and you want to add transport-layer behaviour without rewriting the pipeline.
Performance considerations
xcopy is single-threaded and uses the standard Win32 file cache. For copies dominated by:
- Many small files:
xcopyis bottlenecked by per-file open/close overhead.robocopy /MT:32is 3–5× faster on SSD-to-SSD transfers. - A few huge files:
xcopy /J(unbuffered) avoids cache pressure and matchesrobocopyperformance. - Network shares:
xcopy /Zadds per-file restart but no parallelism.robocopy /MT:8 /Zis dramatically faster.
Quick rule: any copy job that takes more than ~30 seconds with xcopy will benefit from switching to robocopy /MT.
Common scenarios
Build artefact deployment
xcopy C:\Builds\v2.5\dist D:\Deploy\v2.5 /S /E /I /K /Y /F
Output: (per-file paths shown)
Replicate a folder structure as a template
xcopy C:\Templates\newproject D:\Projects\customer-x /T /E /I
Output:
0 File(s) copied
/T creates only the directory hierarchy with no files — useful as a starter scaffold.
Snapshot only the documents you modified today
# Compute "today" once
$today = (Get-Date).Date
Get-ChildItem C:\Users\alicedev\Documents -Recurse -File |
Where-Object { $_.LastWriteTime -ge $today } |
ForEach-Object {
$dest = $_.FullName -replace 'Documents', 'Snapshots\today\Documents'
New-Item -ItemType Directory -Force -Path (Split-Path $dest) | Out-Null
Copy-Item $_.FullName $dest -Force
}
Output: (none)
Verify a copy by recopying with /L (dry run)
rem After a copy, re-run with /L to confirm nothing is left undone
xcopy C:\Source D:\Dest /S /E /I /D /L
Output:
0 File(s) would be copied
A zero count confirms the destination is in sync.
Common pitfalls (continued)
/EXCLUDEis substring, not glob —.gitalso matches.gitignoreand.github\workflows\. Add trailing\for directories or be specific (\.git\).xcopy /Sskips empty folders silently — easy to miss until a project depends on adist\orlogs\folder existing. Always add/Eif the structure matters.- No long-path support — paths over 260 characters fail without the
\\?\prefix thatattribandrobocopyaccept. Userobocopyfor deep trees. /Dwithout a date is sync mode —xcopy C:\Src D:\Dst /D /S /Ecopies only files newer than destination; passing a date (/D:5-1-2026) filters by source mtime instead. The two modes look identical at the call site but behave very differently.COPYCMD=/Yis inherited from the environment — scripts inheriting aCOPYCMD=/Yfrom a parent shell will silently overwrite destination files even without/Yin the command line. Reset withset COPYCMD=if unsure.- ACL preservation requires elevation —
/Osilently strips ACLs whenxcopylacksSeBackupPrivilege. There is no warning. Check the destination's ACLs explicitly after the copy.
Tips
Always pass
/Iwhen the destination doesn't yet exist. Without it,xcopyprompts "Does the destination specify a file name or directory name?" and waits for keystroke — a script will hang.
For interactive ad-hoc copies,
xcopy /S /E /I /Yis the everyday combo. For scripts, preferrobocopy /E /R:3 /W:5— better defaults, better logging, better failure handling.
Use
xcopy /Jfor any single file larger than 1 GB to bypass the Windows file cache and avoid memory pressure during the transfer.
[!WARN]
xcopy /Gdecrypts EFS-encrypted files at the destination. Never use it for backups of confidential data unless the destination is also encrypted by some other means (BitLocker, EFS, third-party encryption).
[!WARN]
/EXCLUDEmatches against the full source path..envexcludes both\.envfiles and any file whose path contains the literal substring.env(such asdev.environment\config.yaml).
Sources
Microsoft Learn — xcopy (updated 2025-09-22) — confirmed /COMPRESS, /SPARSE / /-SPARSE, and /NOCLONE as documented Windows 11 / Server 2022+ additions.