PowerShell Copy and Move Files: Copy-Item and Move-Item

Automated backup scripts, deployment pipelines, and file organization routines all share one thing: they need to copy files in PowerShell or move them reliably. PowerShell’s Copy-Item and Move-Item cmdlets handle this cleanly — supporting single files, entire directory trees, wildcards, and proper error handling. This guide covers every practical pattern you’ll need for copying and moving files in real scripts.
Copy-Item Basic Syntax
Copy a single file from one location to another:
# Copy a single file
Copy-Item -Path 'C:\Logs\app.log' -Destination 'C:\Backup\app.log'
# Copy without specifying filename (keeps original name)
Copy-Item -Path 'C:\Logs\app.log' -Destination 'C:\Backup\'
# Copy and verify with PassThru (returns the new item object)
$copy = Copy-Item -Path 'C:\Logs\app.log' -Destination 'C:\Backup\' -PassThru
Write-Output "Copied to: $($copy.FullName)"
Copied to: C:\Backup\app.log
The destination folder must already exist. If you copy to a path that ends without a filename, PowerShell uses the original filename. If the destination includes a filename, the file is saved with that name.
Copying an Entire Folder Recursively
Use -Recurse to copy a folder with all its contents:
# Copy folder and all contents
Copy-Item -Path 'C:\Projects\WebApp' -Destination 'C:\Backup\WebApp' -Recurse
# Copy to a new name
Copy-Item -Path 'C:\Projects\WebApp' -Destination 'C:\Projects\WebApp-Backup' -Recurse
# Preview with -WhatIf
Copy-Item -Path 'C:\Projects\WebApp' -Destination 'C:\Backup\WebApp' -Recurse -WhatIf
What if: Performing the operation "Copy Directory" on target
"Item: C:\Projects\WebApp Destination: C:\Backup\WebApp".
Always test with -WhatIf first when copying large directory structures. The destination directory does not need to exist when -Recurse is used — PowerShell creates it automatically.
Moving Files with Move-Item
Move-Item works like Copy-Item but removes the source after the operation:
# Move a file
Move-Item -Path 'C:\Downloads\report.xlsx' -Destination 'C:\Users\Public\Documents\'
# Move and rename simultaneously
Move-Item -Path 'C:\Logs\temp.log' -Destination 'C:\Logs\Archive\2026-05-04.log'
# Move all .log files to an archive folder
Get-ChildItem 'C:\Logs' -Filter '*.log' |
Move-Item -Destination 'C:\Logs\Archive\'
# Files moved silently. Check Archive folder.
For moves within the same drive, the operation is near-instant (filesystem rename). Cross-drive moves physically copy then delete, so they’re slower for large files.
Overwriting Existing Files with -Force
By default, Copy-Item and Move-Item throw an error if the destination already exists. Use -Force to overwrite:
# Overwrite if destination exists
Copy-Item -Path 'C:\Config\settings.json' -Destination 'C:\Backup\settings.json' -Force
# Move and overwrite
Move-Item -Path 'C:\Staging\deploy.zip' -Destination 'C:\Production\deploy.zip' -Force
# Check if destination exists before forcing
$dest = 'C:\Backup\app.log'
if (Test-Path $dest) {
Write-Warning "Overwriting: $dest"
}
Copy-Item -Path 'C:\Logs\app.log' -Destination $dest -Force
Copying Multiple Files with Wildcards
Use wildcards in the -Path to copy multiple matching files:
# Copy all .log files
Copy-Item -Path 'C:\Logs\*.log' -Destination 'C:\Backup\'
# Copy files matching a date pattern
Copy-Item -Path 'C:\Logs\2026-05-*.log' -Destination 'C:\Backup\May2026\'
# Copy specific extensions using pipeline
Get-ChildItem 'C:\Projects\WebApp' -Filter '*.config' |
Copy-Item -Destination 'C:\Backup\Configs\'
# All matching files copied to C:\Backup\
Error Handling When Source Is Missing
Scripts should handle missing source files gracefully rather than crashing:
$sourcePath = 'C:\Logs\missing.log'
$destPath = 'C:\Backup\'
try {
if (Test-Path $sourcePath) {
Copy-Item -Path $sourcePath -Destination $destPath -ErrorAction Stop
Write-Output "Backed up: $sourcePath"
} else {
Write-Warning "Source not found: $sourcePath"
}
} catch {
Write-Error "Copy failed: $($_.Exception.Message)"
}
# Robust backup function
function Backup-File {
param(
[string] $Source,
[string] $Destination
)
if (-not (Test-Path $Source)) {
Write-Warning "Skipping (not found): $Source"
return
}
$destDir = Split-Path $Destination -Parent
if (-not (Test-Path $destDir)) {
New-Item -ItemType Directory -Path $destDir -Force | Out-Null
}
Copy-Item -Path $Source -Destination $Destination -Force
Write-Output "Backed up: $(Split-Path $Source -Leaf)"
}
Common Errors and Fixes
-
Destination folder must exist unless using -Force with -Recurse: Copying a file to a non-existent folder path without
-Forcecreates a file named after the folder, not a file inside it. Always ensure the destination directory exists first withNew-Item -ItemType Directory -Force. -
Move-Item fails on cross-drive moves without -Force: When moving between drives (e.g., C: to D:), some configurations require
-Force. If a cross-drive move fails, try adding-Force, or manuallyCopy-ItemthenRemove-Itemthe source.
Related Cmdlets / See Also
Wrapping Up
Copy-Item and Move-Item handle all file and folder copy/move operations in PowerShell. Use -Recurse for directories, -Force to overwrite, and -WhatIf to preview before running destructive operations. Wrap critical copies in try/catch with Test-Path guards for production scripts. Your next step: build an automated daily backup script that copies your most important folders to a backup location.


