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.

cmd
xcopy /?

Output:

css
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).

cmd
xcopy source [destination] [switches]

Output: (shows count of files copied, or error)

Essential options

SwitchMeaning
/SCopy directories and subdirectories (except empty ones)
/ECopy all subdirectories including empty ones (use with /S)
/IIf destination doesn't exist, assume it's a directory
/YOverwrite existing files without prompting
/-YPrompt before overwriting
/HCopy hidden and system files
/ROverwrite read-only destination files
/KPreserve file attributes (default strips read-only)
/OPreserve ownership and ACL information
/ACopy only files with archive bit set
/MSame as /A but clears archive bit after copying
/D:m-d-yCopy only files modified on or after the specified date
/D (no date)Copy only files newer than the destination
/PPrompt before creating each destination file
/FDisplay full source and destination paths during copy
/QQuiet — do not display file names during copy
/LList files that would be copied (dry run)
/CContinue copying even if errors occur
/TCreate destination directory tree but copy no files
/UCopy only files that already exist in destination
/EXCLUDE:fileExclude files matching strings listed in the file
/ZCopy in restartable mode (network resilience)
/BCopy 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.

cmd
rem Copy a folder tree to a new location
xcopy C:\Projects\myapp D:\Backup\myapp /S /E /I /Y

Output:

makefile
C:\Projects\myapp\main.py
C:\Projects\myapp\utils.py
C:\Projects\myapp\tests\test_main.py
3 File(s) copied
cmd
rem Only copy non-empty directories
xcopy C:\Logs D:\Archive\Logs /S /I /Y

Output:

lua
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).

cmd
xcopy C:\Source D:\Dest /S /E /I /K /Y

Output:

scss
4 File(s) copied
cmd
rem Preserve ACLs (requires elevation)
xcopy C:\Source D:\Dest /S /E /I /K /O /Y

Output:

scss
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".

cmd
rem Incremental: copy only changed files
xcopy C:\Work D:\DailyBackup /S /E /I /M /Y

Output:

css
C:\Work\report.docx
1 File(s) copied
cmd
rem Cumulative: copy changed files, leave archive bit set
xcopy C:\Work D:\WeeklyBackup /S /E /I /A /Y

Output:

makefile
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.

cmd
rem Copy only files newer than destination (sync-style)
xcopy C:\Source D:\Dest /S /D /Y

Output:

css
C:\Source\updated_report.docx
1 File(s) copied
cmd
rem Copy only files modified on or after 01 April 2026
xcopy C:\Logs D:\Archive /S /D:4-1-2026 /Y

Output:

lua
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.

cmd
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:

makefile
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.

cmd
xcopy C:\Projects\myapp D:\Backup\myapp /S /E /I /L

Output:

makefile
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

  1. /S without /E skips empty directories — always add /E if the directory structure matters.
  2. Destination ambiguity prompt — without /I, xcopy asks "is destination a file or directory?" Use /I when the destination directory doesn't yet exist.
  3. Read-only files at destinationxcopy fails on read-only destinations unless you pass /R to force overwrite.
  4. Exit codes are not just 0/1xcopy returns 0 (ok), 1 (no files matched), 2 (user pressed Ctrl+C), 4 (init error), or 5 (disk write error). Check %ERRORLEVEL% in scripts.
  5. Paths over 260 charactersxcopy does not support extended-length paths; use robocopy for deep trees.
  6. ACL preservation requires elevation/O silently skips ACL copy if the process lacks SeBackupPrivilege.

Real-world recipes

Mirror a project folder for deployment

cmd
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:

makefile
C:\Projects\myapp\main.py
C:\Projects\myapp\utils.py
4 File(s) copied

Nightly incremental backup script

cmd
@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:

vbnet
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

cmd
xcopy C:\Source D:\Mirror /S /D /Y /C /Q

Output:

scss
2 File(s) copied

Create a skeleton directory tree without files

cmd
xcopy C:\Projects\myapp D:\NewProject /T /E

Output:

scss
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.

SwitchMeaning
/ACopy only files with archive attribute (leave bit set)
/MCopy only files with archive attribute and clear bit
/D[:m-d-y]Date filter — newer than destination, or newer than given date
/PPrompt for each file
/SRecursive, skip empty directories
/ERecursive, include empty directories
/VVerify each file as it is written (slow; mostly obsolete on NTFS)
/WPause before starting (legacy "swap floppy" prompt)
/CContinue on error
/ITreat destination as directory when ambiguous
/QQuiet — suppress per-file output
/FVerbose — full source and destination paths per file
/LList only — dry run
/GAllow copy of encrypted files to a non-EFS destination (decrypts)
/HInclude hidden and system files
/ROverwrite read-only destination files
/TTree only — create directory structure, copy no files
/UUpdate — only copy files that already exist at destination
/KPreserve attributes (read-only is kept)
/NCopy using generated short filenames (8.3)
/OCopy file ownership and ACLs
/XCopy file audit settings and SACL (implies /O)
/YSuppress overwrite prompt
/-YForce overwrite prompt (override COPYCMD=/Y)
/ZRestartable mode for network sources
/BCopy the symbolic link itself, not its target
/JCopy using unbuffered I/O (large files, Win8+)
/COMPRESSRequest SMB network compression during transfer (Windows 11 / Server 2022+)
/SPARSEPreserve sparse-file state on copy (default)
/-SPARSEDisable sparse preservation; fully allocate destination file
/NOCLONESkip 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.

cmd
rem Use /J for ISO files, VM images, video archives
xcopy C:\VMs\bigimage.vhdx D:\Backup\VMs\ /J /Y

Output:

css
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".

cmd
rem Copy an EFS-encrypted file to a USB FAT32 stick (decrypted on arrival)
xcopy C:\Secrets\plans.docx F:\Backup\ /G /Y

Output:

css
C:\Secrets\plans.docx
1 File(s) copied

[!WARN] /G decrypts the file at the destination. The copied file is plaintext and no longer protected by the source's EFS key. Only use /G when 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".

cmd
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:

scss
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.

cmd
xcopy \\myhost\share\bigfile.zip D:\Backup\ /Z /Y

Output:

shell
\\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".

CodeMeaning
0Files copied without error
1No files were found to copy
2User pressed Ctrl+C
4Initialisation error — out of memory, invalid syntax, source path not found
5Disk write error
cmd
@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:

makefile
OK: files copied
powershell
# 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.

Featurexcopyrobocopy
Recursive copy/S /E/E
Empty dirs/E (with /S)included in /E
Multi-threadedno/MT[:n] (default 8, max 128)
Mirror mode (delete extras)no/MIR
Auto-retryno/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 filterno/MAXSIZE /MINSIZE
Exclude files/EXCLUDE:file (substring)/XF pattern (glob)
Exclude dirsno (must use exclusion file)/XD pattern
ACL copy/O /X (requires elevation)/COPY:DATSOU /COPYALL
Long paths (> 260)noyes (default)
Structured logno/LOG /LOG+ /TEE /NFL /NDL /NJH /NJS
Exit codes0–5 (simple)bitmask (0–16)
Move semanticsno/MOVE (delete source after copy)
Backup-API accessno/B /ZB (uses backup privilege)

Equivalent recipes

The same job written with each tool, side by side:

Recursive backup, preserve attributes, overwrite:

cmd
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:

text
C:\Projects\app\main.py
C:\Projects\app\utils.py
C:\Projects\README.md
...
247 File(s) copied

Incremental — changed files only:

cmd
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:

text
C:\Work\notes\monday.md
C:\Work\reports\Q2.xlsx
2 File(s) copied

Mirror (delete destination extras):

cmd
rem xcopy — NOT POSSIBLE; xcopy never deletes at destination
rem robocopy
robocopy C:\Source D:\Mirror /MIR /R:3 /W:5

Output:

text
   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:

cmd
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:

text
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.

powershell
# Basic recursive copy
Copy-Item -Path C:\Source -Destination D:\Dest -Recurse -Force

Output: (none)

powershell
# Include hidden and system files (Force already does this)
Copy-Item -Path C:\Source\* -Destination D:\Dest -Recurse -Force

Output: (none)

powershell
# Exclude patterns (glob, multiple)
Copy-Item -Path C:\Projects\myapp\* `
    -Destination D:\Deploy\myapp `
    -Recurse `
    -Force `
    -Exclude '*.pyc', '*.log', '.env', '.git'

Output: (none)

powershell
# Filter by extension (single glob only)
Copy-Item -Path C:\Source -Destination D:\Dest -Recurse -Filter '*.docx'

Output: (none)

powershell
# 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)

powershell
# Dry run — list what would be copied
Copy-Item -Path C:\Source -Destination D:\Dest -Recurse -WhatIf

Output:

csharp
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

  • -WhatIf is more reliable than xcopy /L for dry runs.
  • -Filter uses real PowerShell globs; xcopy's /EXCLUDE matches substrings of full paths and surprises users.
  • Errors surface as terminating exceptions you can try/catch, rather than just %ERRORLEVEL% codes.
  • Copy-Item works 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 substringxcopy skips a file whenever any exclusion string appears anywhere in the file's full path. This is a powerful but easily misused feature.

cmd
rem exclude.txt — substring matches, not globs
.git\
node_modules\
__pycache__\
.env
.pyc

Output of run:

swift
xcopy C:\Projects\myapp D:\Deploy\myapp /S /E /I /Y /EXCLUDE:exclude.txt
Source pathMatched substringCopied?
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 .pycno
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.

cmd
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.

cmd
rem Long path — fails
xcopy "C:\verylongproject\src\components\NavigationDrawer\subdir\deeplynested\very\long\file.txt" D:\Dest\ /I /Y

Output:

lua
File creation error - The system cannot find the path specified.

For deep trees, prefer robocopy, which supports long paths transparently:

cmd
robocopy "C:\verylongproject" "D:\Dest" *.txt /S /R:3 /W:5

Output: (success)

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.

cmd
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.

VariableEffect
COPYCMDDefault overwrite behaviour — set to /Y to suppress prompt globally; /-Y overrides per-call
cmd
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.

SwitchWhat it doesWhen to use
/COMPRESSRequests 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 / /-SPARSEPreserve (default) or disable preservation of the source's sparse-file extents/-SPARSE when destination filesystem doesn't understand sparse (FAT32, exFAT)
/NOCLONEOpt out of block-clone optimisation when source and destination share a clone-aware volumeBenchmarking, or when you specifically need bytes on different physical blocks
cmd
rem Compressed copy over SMB to a remote share
xcopy C:\Reports \\fileserver01\Backup\Reports /S /E /I /K /Y /COMPRESS

Output:

makefile
C:\Reports\monthly.xlsx
C:\Reports\summary.pdf
2 File(s) copied
cmd
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:

css
C:\VMs\test.vhdx
1 File(s) copied
cmd
rem Disable block cloning to measure raw throughput on ReFS
xcopy D:\Data E:\Mirror /S /E /I /Y /NOCLONE

Output:

python-repl
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: xcopy is bottlenecked by per-file open/close overhead. robocopy /MT:32 is 3–5× faster on SSD-to-SSD transfers.
  • A few huge files: xcopy /J (unbuffered) avoids cache pressure and matches robocopy performance.
  • Network shares: xcopy /Z adds per-file restart but no parallelism. robocopy /MT:8 /Z is 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

cmd
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

cmd
xcopy C:\Templates\newproject D:\Projects\customer-x /T /E /I

Output:

scss
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

powershell
# 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)

cmd
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:

scss
0 File(s) would be copied

A zero count confirms the destination is in sync.

Common pitfalls (continued)

  1. /EXCLUDE is substring, not glob.git also matches .gitignore and .github\workflows\. Add trailing \ for directories or be specific (\.git\).
  2. xcopy /S skips empty folders silently — easy to miss until a project depends on a dist\ or logs\ folder existing. Always add /E if the structure matters.
  3. No long-path support — paths over 260 characters fail without the \\?\ prefix that attrib and robocopy accept. Use robocopy for deep trees.
  4. /D without a date is sync modexcopy C:\Src D:\Dst /D /S /E copies 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.
  5. COPYCMD=/Y is inherited from the environment — scripts inheriting a COPYCMD=/Y from a parent shell will silently overwrite destination files even without /Y in the command line. Reset with set COPYCMD= if unsure.
  6. ACL preservation requires elevation/O silently strips ACLs when xcopy lacks SeBackupPrivilege. There is no warning. Check the destination's ACLs explicitly after the copy.

Tips

Always pass /I when the destination doesn't yet exist. Without it, xcopy prompts "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 /Y is the everyday combo. For scripts, prefer robocopy /E /R:3 /W:5 — better defaults, better logging, better failure handling.

Use xcopy /J for any single file larger than 1 GB to bypass the Windows file cache and avoid memory pressure during the transfer.

[!WARN] xcopy /G decrypts 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] /EXCLUDE matches against the full source path. .env excludes both \.env files and any file whose path contains the literal substring .env (such as dev.environment\config.yaml).

Sources

Microsoft Learn — xcopy (updated 2025-09-22) — confirmed /COMPRESS, /SPARSE / /-SPARSE, and /NOCLONE as documented Windows 11 / Server 2022+ additions.