Repository navigation
Expand file tree
/
Copy pathBackup.ps1
More file actions
99 lines (83 loc) · 3.51 KB
/
Copy pathBackup.ps1
File metadata and controls
99 lines (83 loc) · 3.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# Backup v2026-04-02
# Configuration Constants
$script:Config = @{
MaxBackupFiles = 50
DateTimeFormat = "yyyy-MM-dd_HH-mm-ss"
FileEncoding = "UTF8"
}
$shellApplication = New-Object -ComObject Shell.Application
$windows = $shellApplication.Windows()
$openFolders = @()
$scriptDirectory = [System.IO.Path]::GetFullPath($PSScriptRoot).TrimEnd('\')
$backupDir = [System.IO.Path]::GetFullPath((Join-Path $scriptDirectory "Backups")).TrimEnd('\')
function Replace-GuidWithPathLabel {
param ([string]$folderPath)
# More precise GUID pattern with case-insensitive flag
if ($folderPath -match '(?i)\{[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}\}') {
return "Home"
}
return $folderPath
}
# Preserve window order as provided by Shell
foreach ($window in $windows) {
try {
$rawPath = $window.Document.Folder.Self.Path
if ($rawPath) {
try {
# Normalize for comparison (add trailing slash for recursive check)
$normPath = [System.IO.Path]::GetFullPath($rawPath).TrimEnd('\') + '\'
$normScript = $scriptDirectory + '\'
$normBackup = $backupDir + '\'
# Feature: Ignore the directory the script is in and the Backups folder (Recursive) (#37)
if ($normPath.StartsWith($normScript, [System.StringComparison]::OrdinalIgnoreCase) -or
$normPath.StartsWith($normBackup, [System.StringComparison]::OrdinalIgnoreCase)) {
continue
}
}
catch {
# If path isn't a valid filesystem path (e.g. ::{GUID}), just keep processing
Write-Debug "Skipping normalization for special path: $rawPath"
}
$folderPath = Replace-GuidWithPathLabel $rawPath
$openFolders += $folderPath
}
}
catch {}
}
$tabCount = $openFolders.Count
$dateTime = Get-Date -Format $script:Config.DateTimeFormat
$outputFileName = "Backup_${dateTime}-${tabCount}.txt"
# Ensure Backups folder exists
if (-not (Test-Path $backupDir)) {
New-Item -Path $backupDir -ItemType Directory | Out-Null
}
$tempFile = Join-Path $backupDir "Temp_Backup.txt"
$openFolders | Out-File -FilePath $tempFile -Encoding $script:Config.FileEncoding
$backupFiles = Get-ChildItem -Path $backupDir -Filter "Backup_*.txt" |
Sort-Object { $_.Name -replace "Backup_|\.txt", "" } -Descending
if ($backupFiles.Count -gt 0) {
$lastBackupFile = $backupFiles[0]
# Use hash comparison for better performance
$lastHash = (Get-FileHash -Path $lastBackupFile.FullName -Algorithm MD5).Hash
$newHash = (Get-FileHash -Path $tempFile -Algorithm MD5).Hash
if ($lastHash -eq $newHash) {
# Files are identical, update timestamp of existing backup
(Get-Item $lastBackupFile.FullName).LastWriteTime = Get-Date
Remove-Item $tempFile -Force
}
else {
# Content changed, create new backup
Rename-Item -Path $tempFile -NewName (Join-Path $backupDir $outputFileName)
}
}
else {
# First backup
Rename-Item -Path $tempFile -NewName (Join-Path $backupDir $outputFileName)
}
# Prune old backups
$backupFiles = Get-ChildItem -Path $backupDir -Filter "Backup_*.txt" |
Sort-Object { $_.Name -replace "Backup_|\.txt", "" } -Descending
if ($backupFiles.Count -gt $script:Config.MaxBackupFiles) {
$backupFiles | Select-Object -Skip $script:Config.MaxBackupFiles | Remove-Item -Force
}
exit