Schedule Backup Script

Copy all your valuable Files to an external Drive, to a Network Folder or in the Cloud. Only configure your Folders you want to save, define your Destination, the Logging level and how many of your old backups you want to stay in your Destination.


#Variables, only Change here
$Destination=”C:\Temp” #Copy the Files to this Location
$Versions=”2″ #How many of the last Backups you want to keep
$BackupDirs=”C:\Users\Micha\OneDrive”, “C:\Program Files (x86)\OpenVPN” #What Folders you want to backup
$ExcludeDirs=”C:\Program Files (x86)\OpenVPN\bin”, “C:\Program Files (x86)\OpenVPN\config” #This list of Directories will not be copied
$LogName=”Log.txt” #Log Name
$LoggingLevel=”3″ #LoggingLevel only for Output in Powershell Window, 1=smart, 3=Heavy
$Zip=$true #Zip the Backup Destination
$RemoveBackupDestination=$false #Remove copied files after Zip, only if $Zip is true

#Send Mail Settings
$SendEmail = $false # = $true if you want to enable send report to e-mail (SMTP send)
$EmailTo = ‘’ #user@domain.something (for multiple users use “User01 <>” ,”User02 <>” )
$EmailFrom = ‘’ #matthew@domain
$EmailSMTP = ‘’ #smtp server adress, DNS hostname.

#STOP-no changes from here
#STOP-no changes from here
#Settings – do not change anything from here
$Backupdir=$Destination +”\Backup-“+ (Get-Date -format yyyy-MM-dd)+”-“+(Get-Random -Maximum 100000)+”\”
$StartDate=Get-Date #-format dd.MM.yyyy-HH:mm:ss

Function Logging ($State, $Message) {
$Datum=Get-Date -format dd.MM.yyyy-HH:mm:ss

if (!(Test-Path -Path $Log)) {
New-Item -Path $Log -ItemType File | Out-Null
$Text=”$Datum – $State”+”:”+” $Message”

if ($LoggingLevel -eq “1” -and $Message -notmatch “was copied”) {Write-Host $Text}
elseif ($LoggingLevel -eq “3”) {Write-Host $Text}

add-Content -Path $Log -Value $Text
sleep -Milliseconds 100

#Create Backupdir
Function Create-Backupdir {
New-Item -Path $Backupdir -ItemType Directory | Out-Null
sleep -Seconds 3
Logging “INFO” “Create Backupdir $Backupdir”

#Delete Backupdir
Function Delete-Backupdir {
$Folder=Get-ChildItem $Destination | where {$_.Attributes -eq “Directory”} | Sort-Object -Property $_.CreationTime -Descending:$true | Select-Object -First 1

Logging “INFO” “Remove Dir: $Folder”

$Folder.FullName | Remove-Item -Recurse -Force

#Delete Zip
Function Delete-Zip {
$Zip=Get-ChildItem $Destination | where {$_.Attributes -eq “Archive” -and $_.Extension -eq “.zip”} | Sort-Object -Property $_.CreationTime -Descending:$true | Select-Object -First 1

Logging “INFO” “Remove Zip: $Zip”

$Zip.FullName | Remove-Item -Recurse -Force

#Check if Backupdirs and Destination is available
function Check-Dir {
Logging “INFO” “Check if BackupDir and Destination exists”
if (!(Test-Path $BackupDirs)) {
return $false
Logging “Error” “$BackupDirs does not exist”
if (!(Test-Path $Destination)) {
return $false
Logging “Error” “$Destination does not exist”

#Save all the Files
Function Make-Backup {
Logging “INFO” “Started the Backup”
Logging “INFO” “Count all files and create the Top Level Directories”

foreach ($Backup in $BackupDirs) {
$colItems = (Get-ChildItem $Backup -recurse | Where-Object {$_.mode -notmatch “h”} | Measure-Object -property length -sum)
$FilesCount += Get-ChildItem $Backup -Recurse | Where-Object {$_.mode -notmatch “h”}
Copy-Item -Path $Backup -Destination $Backupdir -Force -ErrorAction SilentlyContinue

$TotalMB=”{0:N2}” -f ($SumMB / 1MB) + ” MB of Files”
Logging “INFO” “There are $SumItems Files with $TotalMB to copy”

foreach ($Backup in $BackupDirs) {
$Files = Get-ChildItem $Backup -Recurse | Where-Object {$_.mode -notmatch “h” -and $ExcludeDirs -notcontains $_.FullName}
foreach ($File in $Files) {
$restpath = $file.fullname.replace($SplitBackup,””)
try {
Copy-Item $file.fullname $($Backupdir+$restpath) -Force -ErrorAction SilentlyContinue |Out-Null
Logging “INFO” “$file was copied”
catch {
Logging “ERROR” “$file returned an error an was not copied”
$Items += (Get-item $file.fullname).Length
$status = “Copy file {0} of {1} and copied {3} MB of {4} MB: {2}” -f $count,$SumItems,$file.Name,(“{0:N2}” -f ($Items / 1MB)).ToString(),(“{0:N2}” -f ($SumMB / 1MB)).ToString()
$Text=”Copy data Location {0} of {1}” -f $Index ,$BackupDirs.Count
Write-Progress -Activity $Text $status -PercentComplete ($Items / $SumMB*100)
if ($File.Attributes -ne “Directory”) {$count++}
$SumTotalMB=”{0:N2}” -f ($Items / 1MB) + ” MB of Files”
Logging “INFO” “———————-”
Logging “INFO” “Copied $SumCount files with $SumTotalMB”
Logging “INFO” “$ErrorCount Files could not be copied”

# Send e-mail with reports as attachments
if ($SendEmail -eq $true) {
$EmailSubject = “Backup Email $(get-date -format MM.yyyy)”
$EmailBody = “Backup Script $(get-date -format MM.yyyy) (last Month).`nYours sincerely `Matthew – SYSTEM ADMINISTRATOR”
Logging “INFO” “Sending e-mail to $EmailTo from $EmailFrom (SMTPServer = $EmailSMTP) ”
### the attachment is $log
Send-MailMessage -To $EmailTo -From $EmailFrom -Subject $EmailSubject -Body $EmailBody -SmtpServer $EmailSMTP -attachment $Log

#Bcreate Backup Dir
Logging “INFO” “———————-”
Logging “INFO” “Start the Script”

#Check if Backupdir needs to be cleaned and create Backupdir
$Count=(Get-ChildItem $Destination | where {$_.Attributes -eq “Directory”}).count
Logging “INFO” “Check if there are more than $Versions Directories in the Backupdir”

if ($count -gt $Versions) {



$CountZip=(Get-ChildItem $Destination | where {$_.Attributes -eq “Archive” -and $_.Extension -eq “.zip”}).count
Logging “INFO” “Check if there are more than $Versions Zip in the Backupdir”

if ($CountZip -gt $Versions) {



#Check if all Dir are existing and do the Backup

if ($CheckDir -eq $false) {
Logging “ERROR” “One of the Directory are not available, Script has stopped”
} else {

$Enddate=Get-Date #-format dd.MM.yyyy-HH:mm:ss
$span = $EndDate – $StartDate

Logging “INFO” “Backupduration $Minutes Minutes and $Seconds Seconds”
Logging “INFO” “———————-”
Logging “INFO” “———————-”

if ($Zip)
Logging “INFO” “Compress thew Backup Destination”
Compress-Archive -Path $Backupdir -DestinationPath ($Destination+(“\”+$Backupdir.Replace($Destination,”).Replace(‘\’,”)+”.zip”)) -CompressionLevel Optimal -Force

If ($RemoveBackupDestination)
Logging “INFO” “Backupduration $Minutes Minutes and $Seconds Seconds”

#Remove-Item -Path $BackupDir -Force -Recurse
get-childitem -Path $BackupDir -recurse -Force | remove-item -Confirm:$false -Recurse
get-item -Path $BackupDir | remove-item -Confirm:$false -Recurse

Write-Host “Press any key to close …”

$x = $host.UI.RawUI.ReadKey(“NoEcho,IncludeKeyDown”)

Be the first to comment

Leave a Reply

Your email address will not be published.