Skip to content

Instantly share code, notes, and snippets.

@gideonip
Created October 27, 2025 01:53
Show Gist options
  • Select an option

  • Save gideonip/f42f41053329fb017d22c2661701223f to your computer and use it in GitHub Desktop.

Select an option

Save gideonip/f42f41053329fb017d22c2661701223f to your computer and use it in GitHub Desktop.
CopyFile
<#
CopyUserFiles.ps1
Copies specific file types from user folders while preserving structure.
#>
param(
[string]$SourceRoot = "C:\Users",
[string]$DestinationRoot = "D:\Backup",
[string[]]$FoldersToInclude = @("Desktop", "Documents", "Downloads", "Pictures"),
[string[]]$Extensions = @("doc","docx","xls","xlsx","ppt","pptx","gif","jpeg","jpg","png","pst"),
[switch]$WhatIf,
[string]$LogFile = "C:\Temp\CopyUserFiles.log"
)
# --- Function for logging ---
function Log {
param([string]$msg)
$line = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - $msg"
$line | Out-File -FilePath $LogFile -Append -Encoding UTF8
Write-Output $line
}
Log "========== Copy started =========="
Log "Source: $SourceRoot"
Log "Destination: $DestinationRoot"
Log "Folders: $($FoldersToInclude -join ', ')"
Log "Extensions: $($Extensions -join ', ')"
# Convert extensions to regex
$extRegex = "\.({0})$" -f ($Extensions -join "|")
# Ensure destination exists
if (!(Test-Path $DestinationRoot)) {
New-Item -Path $DestinationRoot -ItemType Directory -Force | Out-Null
Log "Created destination root: $DestinationRoot"
}
foreach ($userFolder in Get-ChildItem -Path $SourceRoot -Directory) {
foreach ($subFolder in $FoldersToInclude) {
$srcPath = Join-Path $userFolder.FullName $subFolder
if (!(Test-Path $srcPath)) {
Log "Skipping missing: $srcPath"
continue
}
Log "Processing folder: $srcPath"
# Find files recursively matching extensions
$files = Get-ChildItem -Path $srcPath -Recurse -File -ErrorAction SilentlyContinue |
Where-Object { $_.Extension -match $extRegex }
foreach ($file in $files) {
# Build relative path
$relativePath = $file.FullName.Substring($SourceRoot.Length).TrimStart("\")
$destPath = Join-Path $DestinationRoot $relativePath
# Create destination folder if needed
$destDir = Split-Path $destPath
if (!(Test-Path $destDir)) {
if (-not $WhatIf) {
New-Item -Path $destDir -ItemType Directory -Force | Out-Null
}
}
# Copy file
if (-not $WhatIf) {
Copy-Item -Path $file.FullName -Destination $destPath -Force -ErrorAction SilentlyContinue
}
Log "Copied: $relativePath"
}
}
}
Log "========== Copy completed =========="
@gideonip
Copy link
Copy Markdown
Author

How to run:

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\CopyUserFiles.ps1 -SourceRoot "C:\Users" -DestinationRoot "D:\Backup"

Preview only

.\CopyUserFiles.ps1 -SourceRoot "C:\Users" -DestinationRoot "D:\Backup" -WhatIf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment