<#
Purpose: To create an intelligent backup system for large directories.
Notes: I wrote this to perform a renditional backup of a large and complex directory.
I've found that (for whatever reason) files keep getting removed from the
diectory, so I've added a feature to keep track of deleted items as well.
I know that there are applications to do this, but I wanted to see if I
could do it myself! I'm please with the overall outcome, but would appreciate
any feedback!
Issues: No known issues. Use at your own peril!
#>
#Set Directory Paths
$SourceDirectory = "C:\SourceDirectory\"
$BackupLocation = "C:\BackupDirectory\"
#Get all files contained in Source Folder for processing
$SourceFiles = Get-ChildItem -Path $SourceDirectory -File -Recurse
#Create an array to store the output
$MoveStats = New-Object System.Collections.ArrayList
#Iterate through all of the files in SourceDirectory
$MoveStats = ForEach($File in $SourceFiles){
$OldPath = ($File.FullName)
$NewPath = $OldPath.Replace($SourceDirectory,$BackupLocation)
#Create new object to store output
$FileObject = New-Object -TypeName PSCustomObject -Property @{
File = $File.Name
OriginalPath = $File.FullName
BackupPath = $null
Action = $null
RenditionPath = "N/A"
}
#Check for existing file in Backup Location
if(Test-Path $NewPath){
#File exists. Check to see if needs updating
if(($File.LastWriteTime) -gt ((Get-Item $NewPath).LastWriteTime)){
#Rename existing backup, appending date/time to extention
$NewName = (-join(($NewPath),"-",(Get-Date -Format "yyyyMMdd.HHmmss"),".BACKUP"))
Get-Item -Path $NewPath | Rename-Item -NewName $NewName
#Copy item to backup location
Copy-Item -Path $File.FullName -Destination $NewPath
#Update FileObject properties
$FileObject.BackupPath = $NewPath
$FileObject.Action = "Rendition Saved."
$FileObject.RenditionPath = $NewName
}
else{
#No action taken
$FileObject.BackupPath = $NewPath
$FileObject.Action = "No action taken."
}
}
else{
#File does not exist. Copy file.
New-Item -ItemType File -Path $NewPath -Force | Out-Null
Copy-Item -Path $OldPath -Destination $NewPath
$FileObject.BackupPath = $NewPath
$FileObject.Action = "New File Copied."
}
#Returning Object
$FileObject
}
#Gather BackupFile inventory in order to mark deletions, ignoring Backup and Deleted Folders
$BackupDirectory = Get-ChildItem $BackupLocation -File -Recurse
$BackupFiles = $BackupDirectory | Where {$_.name -notmatch ".BACKUP" -and $_.name -notmatch ".DELETED"}
ForEach($BackupFile in $BackupFiles){
#Build FileName for checking against SourceFiles
$BackupFileName = ($BackupFile.FullName).replace($BackupLocation,$SourceDirectory)
#Check for missing BackupFile in SourceFile Directory
if($SourceFiles.FullName -notcontains $BackupFileName){
#File does not exist. Rename it, appending Date/Time and "-DELETED"
$DeletedName = (-join($BackupFile.FullName,"-",(Get-Date -Format "yyyyMMdd.HHmmss"),".DELETED"))
Rename-Item -Path ($BackupFile.FullName) -NewName $DeletedName
#Add New Object to MoveStats
$MoveStats += New-Object -TypeName PSCustomObject -Property @{
File = $BackupFile.Name
OriginalPath = "N/A"
BackupPath = $BackupFile.FullName
Action = "Deleted"
RenditionPath = "N/A"
}
}
}
#Display Output
$MoveStats | Select File,OriginalPath,BackupPath,Action,RenditionPath | Out-GridView
Read more ...