Copy-Item for most jobs, with -Recurse for folders. For very large trees, restartable copies or mirroring, call robocopy instead.
Copying is one of those tasks where the simple answer is right most of the time and badly wrong occasionally. Here is both halves of that.
Copy-Item, the Everyday Answer
# one file Copy-Item "D:\Data\report.csv" -Destination "E:\Backup\report.csv" # a whole folder, including everything inside it Copy-Item "D:\Data" -Destination "E:\Backup\Data" -Recurse # only certain files Copy-Item "D:\Data\*.csv" -Destination "E:\Backup\" # overwrite read-only files at the destination Copy-Item "D:\Data\*" -Destination "E:\Backup\" -Recurse -Force
Copying Only What You Choose
The pipeline is where Copy-Item earns its place, because you can select files with any logic you like before copying them:
# only files changed in the last day
Get-ChildItem "D:\Data" -Recurse -File |
Where-Object LastWriteTime -gt (Get-Date).AddDays(-1) |
Copy-Item -Destination "E:\Backup\" -WhatIf
When to Use robocopy Instead
robocopy ships with Windows, retries locked files, resumes, and can mirror. PowerShell calls it perfectly well:
# copy a tree, retry twice with a 5 second wait, multi-threaded
robocopy "D:\Data" "E:\Backup\Data" /E /R:2 /W:5 /MT:8
# MIRROR the destination to match the source - deletions included
robocopy "D:\Data" "E:\Backup\Data" /MIR /R:2 /W:5
# check how it went. robocopy exit codes below 8 are success
if ($LASTEXITCODE -lt 8) { "copy ok" } else { "copy FAILED: $LASTEXITCODE" }
/L first, which lists what it would do and changes nothing.The exit code check matters too: robocopy does not use 0 for success the way most tools do. Anything below 8 means it worked, with the number describing what it did.
Related
- Get a Folder Size in PowerShell
- Delete Files in PowerShell
- Zip and Unzip Files with PowerShell
- PowerShell Complete Guide
If SQL Server is part of your day job, my current work lives over at sqldba.blog: production DBA scripts, an error library and the SSMS guide.
Leave a Reply