I have a PS script that renames recycle bin files
to their original names and folders
turns this
into this

# Restore-RecycleNames-With-DriveFolder.ps1
# Creates top-level drive letter folders (e.g. G_) under 'fixed'
$sourcePath = Get-Location
$fixedRoot = Join-Path $sourcePath "fixed"
if (-not (Test-Path $fixedRoot)) {
New-Item -Path $fixedRoot -ItemType Directory | Out-Null
Write-Host "Created folder: $fixedRoot" -ForegroundColor Green
}
Write-Host "=== Recycle Bin Recovery Script (Drive Letter as Top-Level Folder) ===" -ForegroundColor Cyan
Write-Host "This script will:"
Write-Host " - Read original filenames/paths from $I files"
Write-Host " - Rename matching $R files to their original names"
Write-Host " - Create top-level folder for each drive letter (e.g. G:\ → G_)"
Write-Host " - Rebuild remaining folder structure under that drive folder"
Write-Host " - Move renamed files into correct subfolders"
Write-Host " - Show detailed log of every file processed"
Write-Host ""
Write-Host "Current folder: $sourcePath"
Write-Host "Output will be in: $fixedRoot"
Write-Host "----------------------------------------" -ForegroundColor Gray
Write-Host ""
# Execution policy reminder
Write-Host "If you get a policy error, run this first (copy-paste):" -ForegroundColor Yellow
Write-Host " Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass" -ForegroundColor Yellow
Write-Host ""
$countSuccess = 0
$countFallback = 0
$countSkipped = 0
Get-ChildItem -Path $sourcePath -Filter '$I*' | ForEach-Object {
$iFile = $_.FullName
$rFileName = $_.Name -replace '^\$I', '$R'
$rFile = Join-Path $sourcePath $rFileName
if (-not (Test-Path $rFile)) {
Write-Host "SKIP: No matching $rFileName found for $iFile" -ForegroundColor Yellow
$countSkipped++
return
}
$originalPath = $null
$originalName = $null
$driveFolder = ""
$relativeDir = ""
try {
$bytes = [System.IO.File]::ReadAllBytes($iFile)
if ($bytes.Length -ge 20) {
# Modern format (Vista+)
$pathLength = [BitConverter]::ToUInt32($bytes[24..27], 0)
if ($pathLength -gt 0 -and $pathLength -lt 10000 -and ($pathLength * 2 + 28) -le $bytes.Length) {
$pathBytes = $bytes[28..($pathLength * 2 + 27)]
$originalPath = [System.Text.Encoding]::Unicode.GetString($pathBytes).TrimEnd("`0")
}
else {
# XP/2003 fallback
$pathStartCandidates = @(20, 24, 16, 28)
foreach ($start in $pathStartCandidates) {
if ($start -ge $bytes.Length) { continue }
$pathEnd = $bytes.Length - 1
for ($i = $start; $i -lt $pathEnd - 1; $i += 2) {
if ($bytes[$i] -eq 0 -and $bytes[$i+1] -eq 0) {
$pathBytes = $bytes[$start..($i-1)]
$originalPath = [System.Text.Encoding]::Unicode.GetString($pathBytes).TrimEnd("`0")
break
}
}
if ($originalPath) { break }
}
}
if ($originalPath) {
$originalName = [System.IO.Path]::GetFileName($originalPath)
$originalDir = [System.IO.Path]::GetDirectoryName($originalPath)
# Extract drive letter and build top-level folder as "G_"
if ($originalDir -match '^([A-Z]):\\') {
$driveLetter = $matches[1]
$driveFolder = "${driveLetter}_"
$relativeDir = $originalDir -replace "^[A-Z]:\\", ""
} else {
$driveFolder = "UNKNOWN_DRIVE_"
$relativeDir = $originalDir
}
}
}
}
catch {
Write-Host "ERROR reading $iFile : $_" -ForegroundColor Red
}
# Fallback if no valid path/name
if (-not $originalName -or $originalName -eq "") {
$originalName = "UNKNOWN_ORIGINAL_" + $rFileName
$driveFolder = "UNKNOWN_DRIVE_"
$relativeDir = ""
Write-Host "FALLBACK: $rFileName → $originalName (no valid path in $iFile)" -ForegroundColor Magenta
$countFallback++
}
else {
Write-Host "SUCCESS: $rFileName → $originalName" -ForegroundColor Green
$countSuccess++
}
$extension = [System.IO.Path]::GetExtension($rFile)
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($originalName)
$newName = $baseName + $extension
# Build destination: fixed \ DRIVE_ \ relative folders \ filename
$destDir = Join-Path $fixedRoot $driveFolder
if ($relativeDir) {
$destDir = Join-Path $destDir $relativeDir
}
if (-not (Test-Path $destDir)) {
New-Item -Path $destDir -ItemType Directory -Force | Out-Null
}
$newPath = Join-Path $destDir $newName
$counter = 1
while (Test-Path $newPath) {
$newName = "${baseName}_${counter}${extension}"
$newPath = Join-Path $destDir $newName
$counter++
}
Write-Host " Moving to: $newPath" -ForegroundColor DarkCyan
Move-Item -Path $rFile -Destination $newPath -Force
}
Write-Host ""
Write-Host "----------------------------------------" -ForegroundColor Gray
Write-Host "Finished processing!" -ForegroundColor Cyan
Write-Host "Success (real names restored): $countSuccess files" -ForegroundColor Green
Write-Host "Fallback (no name extracted): $countFallback files" -ForegroundColor Magenta
Write-Host "Skipped (no matching file): $countSkipped files" -ForegroundColor Yellow
Write-Host ""
Write-Host "All recovered files with drive-letter-as-folder structure are now under:"
Write-Host " $fixedRoot" -ForegroundColor White
Write-Host ""
pause
-- Alandata Data Recovery -
(949)287-3282 "Cleanroom Data Recovery of RAID, VMware, NAS, Linux, Tape, Disk, Forensics"