PS: Start-Archive

This script can archive files and folders to zip / 7z files. Before archiving the files it can create hashes on the files so the integrity can be verified afterwards. (7z executable is required).


Requirements

  • for checksums > SHA1 checksum files Windows version greater Windows 7 is required
  • for archiving 7z (at least the commandline version) is required (see >> download)

Usage

See examples within the script. Some KB articles that describe advanced usage will be published later on...

Parameters:

  • InputPath
    [STRING] Mandatory parameter that provides the source path for the archive operations
  • ArchiveFileName
    [STRING] Mandatory parameter that provides the path and file name to the archive file in which the source files get archived
  • SevenZipExecutablePath
    [STRING] Mandatory parameter that provides to path to the 7zip executable
  • SevenZipParameters
    [STRING] Parameter that can be used to change 7zip compression parameters (Default is "a" -> Add files to archive)
  • HashAlgorithm
    [STRING] Parameter to change the hashing algorithm used when creating file hashes. Supported are: MD5, SHA1 (default), SHA256 and SHA512
    SHA256 and SHA512 are not supported on all operating systems (tested on Windows 8 / Server 2012 and higher)
  • InputFileMask
    [STRING] This parameter controls the input file mask and can be used to only archive files of a given file type.
  • InputMinFileAgeDays
    [INT] Can be used if only files with a creation date older then the provided number of days should be processed.
    Default value is 0 (zero) which means there is no limit on file age. So all files regardless of there creation date get archived.
  • LogFilePath
    [STRING] Path where the log file should be created (If logging is enabled)
  • LogFileBaseName
    [STRING] Name of the log file. This string gets appended to the date time value (.PARAMETER LogFileDateTime)
    Default path is the script executable directory
  • LogFileDateTime
    [STRING] Date time formatting string that can be used to create log files on for example a daily basis (yyyyMMdd)
  • CreateHashForEachFile
    [BOOL] Enabled by default it creates hash file for each file that gets processed.
  • CreateHashForAllFiles
    [BOOL] Enabled by default this parameter creates a file in the input directory that holds all processed filenames and hashes
  • CreateArchiveHash
    [BOOL] Enabled by default this parameter creates a hash file for the compressed archive file
  • NoLogging
    [BOOL] Disabled by default. This parameter can be used to prevent log file creation
  • DebugLogging
    [BOOL] Disabled by default. This parameter can be used to enable debug logging (this increases the size of the log file)
    To enable debug logging the parameter NoLogging needs to be
  • DebugToScreen
    [BOOL] Disabled by default. When enabled and DebugLogging is also enabled all information written to the log file get displayed
    also to the console window.
  • DeleteSourceFiles
    [BOOL] Disabled by default this parameter can be used to delete processed source files and created hashes when the archive process is finished
    WARNING: Please verifiy if the script operates correctly before enabling this switch!
  • DeleteEmptyFolders
    [BOOL] Disabled by default this parameter can be used to delete empty folders when the archive process is finished
  • RemoveExistingHashFiles
    [BOOL] Enabled by default this parameter ensures hash files can overwrite existing hash files for the processed files
  • RemoveExistingArchiveFile
    [BOOL] Disabled by default this parameter can be used to delete an existing target archive file. Enable this parameter to ensure only files from
    the current run reside within the archive. But handle it with care because of potential data loss!

Version History:

  • 1.0.0: Initial release
  • 1.0.2: New Logging functionalities; Excluded files now also get exluded from the archive not only from creating hashes...
  • 1.0.3: License change to MIT license; some bugfixes

Script code:

	
##------------------------------------------------------------------------------------------------
##
##  Start-Archive.ps1
##
##   Version 1.0.3
##
##   
##   Copyright (c) 2016 Martin Mueller - www.sh-soft.com
##   
##   Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
##   and associated documentation files (the "Software"), to deal in the Software without 
##   restriction, including without limitation the rights to use, copy, modify, merge, publish, 
##   distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
##   Software is furnished to do so, subject to the following conditions:
##   
##   The above copyright notice and this permission notice shall be included in all copies or 
##   substantial portions of the Software.
##   
##   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
##   BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
##   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
##   DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
##   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
##   (The MIT License (MIT))
##
##------------------------------------------------------------------------------------------------

<#
.SYNOPSIS
Reads given files and creates checksums for all of them, then it copies the files to an archive, creates an additional checksum file and if wanted deletes the source files and folders.


.DESCRIPTION
Reads given files and creates checksums for all of them, then it copies the files to an archive, creates an additional checksum file and if wanted deletes the source files and folders.
 

.PARAMETER InputPath

[STRING] Mandatory parameter that provides the source path for the archive operations


.PARAMETER ArchiveFileName

[STRING] Mandatory parameter that provides the path and file name to the archive file in which the source files get archived


.PARAMETER SevenZipExecutablePath

[STRING] Mandatory parameter that provides to path to the 7zip executable


.PARAMETER SevenZipParameters

[STRING] Parameter that can be used to change 7zip compression parameters (Default is "a" -> Add files to archive)


.PARAMETER HashAlgorithm

[STRING] Parameter to change the hashing algorithm used when creating file hashes. Supported are: MD5, SHA1 (default), SHA256 and SHA512

SHA256 and SHA512 are not supported on all operating systems (tested on Windows 8 / Server 2012 and higher)



.PARAMETER InputFileMask

[STRING] This parameter controls the input file mask and can be used to only archive files of a given file type.


.PARAMETER InputMinFileAgeDays

[INT] Can be used if only files with a creation date older then the provided number of days should be processed.

Default value is 0 (zero) which means there is no limit on file age. So all files regardless of there creation date get archived.


.PARAMETER LogFilePath

[STRING] Path where the log file should be created (If logging is enabled)


.PARAMETER LogFileBaseName

[STRING] Name of the log file. This string gets appended to the date time value (.PARAMETER LogFileDateTime)

Default path is the script executable directory


.PARAMETER LogFileDateTime

[STRING] Date time formatting string that can be used to create log files on for example a daily basis (yyyyMMdd)


.PARAMETER CreateHashForEachFile

[BOOL] Enabled by default it creates hash file for each file that gets processed.


.PARAMETER CreateHashForAllFiles

[BOOL] Enabled by default this parameter creates a file in the input directory that holds all processed filenames and hashes


.PARAMETER CreateArchiveHash

[BOOL] Enabled by default this parameter creates a hash file for the compressed archive file


.PARAMETER NoLogging

[BOOL] Disabled by default. This parameter can be used to prevent log file creation


.PARAMETER DebugLogging

[BOOL] Disabled by default. This parameter can be used to enable debug logging (this increases the size of the log file)

To enable debug logging the parameter NoLogging needs to be $false


.PARAMETER DebugToScreen

[BOOL] Disabled by default. When enabled and DebugLogging is also enabled all information written to the log file get displayed 

also to the console window.


.PARAMETER DeleteSourceFiles

[BOOL] Disabled by default this parameter can be used to delete processed source files and created hashes when the archive process is finished

WARNING: Please verifiy if the script operates correctly before enabling this switch!


.PARAMETER DeleteEmptyFolders

[BOOL] Disabled by default this parameter can be used to delete empty folders when the archive process is finished


.PARAMETER RemoveExistingHashFiles

[BOOL] Enabled by default this parameter ensures hash files can overwrite existing hash files for the processed files


.PARAMETER RemoveExistingArchiveFile = 

[BOOL] Disabled by default this parameter can be used to delete an existing target archive file. Enable this parameter to ensure only files from

the current run reside within the archive. But handle it with care because of potential data loss!


.EXAMPLE
Quick archive with mostly default parameters
.\Start-Archive.ps1 -InputPath "C:\inetpub\logs\LogFiles" -ArchiveFileName "C:\archive\LogFiles.zip" -SevenZipExecutablePath "C:\script\7za.exe"


.EXAMPLE 
Start archive process for each subfolder within C:\inetpub\logs\LogFiles for all files older then 10 days. Each folder will be placed to an individual archive file.
Get-ChildItem "C:\inetpub\logs\LogFiles" | Where-Object {$_.PSIsContainer -eq $true} | Foreach-Object { .\Start-Archive.ps1 -InputPath $_.FullName -ArchiveFileName ("c:\archive\test\"+$_.Name+".zip") -SevenZipExecutablePath "C:\script\7za.exe" -InputMinFileAgeDays 10}
#>

#------------------------------------------------------------------------------------------------
# Parameter block
#------------------------------------------------------------------------------------------------
param( 
	[Parameter(Mandatory=$TRUE)] 
		[String] $InputPath, 
	[Parameter(Mandatory=$TRUE)] 
		[String] $ArchiveFileName,
	[Parameter(Mandatory=$TRUE)] 
		[String] $SevenZipExecutablePath,
	[String] $SevenZipParameters = "a",
	[String] $HashAlgorithm="SHA1",
	[String] $InputFileMask="*",
	[int] $InputMinFileAgeDays=0,
	[String] $LogFilePath = (Split-Path -Parent -Path $MyInvocation.MyCommand.Definition),
	[String] $LogFileBaseName = "_ArchiveJob.log",
	[String] $LogFileDateTime = "yyyyMMdd.HHmmss",
	[bool] $CreateHashForEachFile = $true,
	[bool] $CreateHashForAllFiles = $true,
	[bool] $CreateArchiveHash = $true, 
	[bool] $NoLogging = $false, 
	[bool] $DebugLogging = $false,
	[bool] $DebugToScreen = $false, 
	[bool] $DeleteSourceFiles = $false,
	[bool] $DeleteEmptyFolders = $false,
	[bool] $RemoveExistingHashFiles = $true,
	[bool] $RemoveExistingArchiveFile = $false
)

##------------------------------------------------------------------------------------------------
## Initialization
##------------------------------------------------------------------------------------------------
begin {
	#------------------------------------------------------------------------------------------------
	# Configure Environment and basic functions
	#------------------------------------------------------------------------------------------------

	# LOGWRITER
	$Date = Get-Date -Format $LogFileDateTime
	function Write-Log ($Entry, $DebugEntry) {
		if (-not $NoLogging) {
			$DateTime = Get-Date -Format "yyyyMMdd;HHmmss;"
			$FileName = Join-Path -Path $LogFilePath -ChildPath ($Date + $LogFileBaseName)
			## USER INTERFACE
			if ($DebugToScreen) {
				if ($Entry) {
					Write-Host -ForegroundColor Cyan ($DateTime+$Entry)
				}
				if ($DebugEntry) {
					Write-Host -ForegroundColor Magenta ($DateTime+"[DEBUG]") -nonewline
					Write-Host -ForegroundColor Cyan $DebugEntry
				}
			}
			if ($LogFilePath.Length -eq $null) {
				$FileName = ($Date + "-" + $LogFileBaseName)
			}
			if ($Entry) {
				Add-Content -Path $FileName -Value ($DateTime + $Entry)
			}
			if ($DebugLogging -and $DebugEntry) {
				Add-Content -Path $FileName -Value ($DateTime +" [DEBUG] "+ $DebugEntry)
			}
		}
	}
	# FILEHASH GENERATOR
	function Create-FileHash ($FileName, $HashAlgorithm) {
		try {
			$file = [System.IO.File]::Open($FileName,[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)
			$HASH = (([System.BitConverter]::ToString($CProvider.ComputeHash($file))).Replace("-", "")).ToLower()
			$file.Dispose()
			return ($HASH)
		}
		catch {
			Write-Log -Entry "[ERROR] creating hash for file: $FileName"
			return ("[ERROR]")
		}
	}
	# Remove archive include file
	function Remove-IncludeListFile {
		if (Test-Path -Path $IncludeListFileName) {
			try {
				Remove-Item -Path $IncludeListFileName -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
				Write-Log -DebugEntry "Removing archive include file: $IncludeListFileName"
			}
			catch  {
				Write-Log -Entry "Failed to remove archive include file: $ArchiveFileName."
				Write-Error "[ERROR] Failed to remove archive include file!"
				exit
			}
		}
	}
	# Add file to include archive file
	function Add-FileToIncludeFile ($FilePath) {
		try {
			Add-Content -Path $IncludeListFileName -Value ($FilePath.ToLower())
			Write-Log -DebugEntry "Adding file to include list: $FilePath"
		}
		catch {
			Write-Log -Entry "Failed to write to include file: $ArchiveFileName."
			Write-Error "[ERROR] Failed to write to include file!"
			exit
		}
	}

	### USER INTERFACE
	Write-Log -Entry "Beginning File Archive..." -DebugEntry (Get-Date)
	Write-Host -ForegroundColor Green "Beginning File Archive..."
	Write-Host -ForegroundColor Yellow "LogFilePath: " -NoNewline
	Write-Host $LogFilePath
	Write-Host -ForegroundColor Yellow "Input path: " -NoNewline
	Write-Host $InputPath
	# CHECK: InputPath clean up
	if ($InputPath[($InputPath.Length)-1] -ne "\") {
		$InputPath = $InputPath+"\"
	}
	$InputPath = $InputPath.ToLower()

	#------------------------------------------------------------------------------------------------
	# CHECK: Archive Path
	$ArchiveFileName = $ArchiveFileName.ToLower()
	$IncludeListFileName = ($ArchiveFileName+".include")
	$ArchivePath = ((Split-Path -Path $ArchiveFileName -Parent)+ "\")
	if ($InputPath.Length -ge $ArchivePath.Length) {
		if (($InputPath.Split(1,$ArchivePath.Length)) -eq $ArchivePath) {
			Write-Log -Entry "[Error] Archive file is within input path"
			Write-Error "[ERROR] Archive file is within input path"
			exit
		}
		if ($RemoveExistingArchiveFile) {
			try {
				Remove-Item -Path $ArchiveFileName -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
				Write-Log -Entry "Removing existing archive file." -DebugEntry $ArchiveFileName
			}
			catch  {
				Write-Log -Entry "Failed to remove existing archive file: $ArchiveFileName."
				Write-Error "[ERROR] Failed to remove existing archive file!"
				exit
			}
		}
		Remove-IncludeListFile
	}
	
	#------------------------------------------------------------------------------------------------
	# CHECK: 7z executable
	if (-not (Test-Path -Path "$SevenZipExecutablePath")) {
		Write-Log -Entry "[Error] Path to 7z executable not found"
		Write-Error "[ERROR] Path to 7z executable not found"
		exit
	}
	
	#------------------------------------------------------------------------------------------------
	# CHECK: File age...
	if ($InputMinFileAgeDays -gt 0) {
		$InputMinFileAgeDays = 0-$InputMinFileAgeDays
	}
	if ($InputMinFileAgeDays -ne 0) {
		$ArchiveFilesOlderThen = ((Get-Date).AddDays($InputMinFileAgeDays)).Date
		### USER INTERFACE
		Write-Host -ForegroundColor Green "Processing files older then date: " -NoNewLine
		Write-Host $ArchiveFilesOlderThen
		Write-Log -Entry "Archiving files with creation date older then: $ArchiveFilesOlderThen"
	}
	
	#------------------------------------------------------------------------------------------------
	# CHECK: Input path...
	if (-not (Test-Path -Path $InputPath)) {
		Write-Log -Entry "[Error] Input Path not accessible"
		Write-Error "[ERROR] Input Path not accessible"
		exit
	}

	#------------------------------------------------------------------------------------------------
	# CHECK: Hashing ‎algorithm
	try {
		$HashAlgorithm = ([string]$HashAlgorithm).ToLower()
		Write-Log -DebugEntry ("Testing hashing algorithm successful")
	}
	catch {
		Write-Error -Exception "Invalid Input Type" -Message "The entered hash algorithm is provided in the wrong format [STRING] is required!"
	}
	switch ($HashAlgorithm) { 
		"md5" { 
			$ExpectedHashSize = 128
			$HashfileEnding = "md5"
			$CProvider = new-object System.Security.Cryptography.MD5CryptoServiceProvider
			Write-Log -DebugEntry ("Settings for algorithm: $HashfileEnding applied!")
			break
		} 
		"sha1" { 
			$ExpectedHashSize = 160
			$HashfileEnding = "sha"
			$CProvider = new-object System.Security.Cryptography.SHA1CryptoServiceProvider
			Write-Log -DebugEntry ("Settings for algorithm: $HashfileEnding applied!")
			break
		} 
		"sha256" { 
			$ExpectedHashSize = 256
			$HashfileEnding = "sha256"
			try { 
				$CProvider = new-object System.Security.Cryptography.SHA256CryptoServiceProvider 
				Write-Log -DebugEntry ("Settings for algorithm: $HashfileEnding applied!")
			}
			catch { 
				Write-Log -DebugEntry ("Settings for algorithm: $HashfileEnding failed!")
				Write-Error -Message "SHA256 seems not to work on this system..." 
			}			
			break
		} 
		"sha512" { 
			$ExpectedHashSize = 512
			$HashfileEnding = "sha512"
			try {
				$CProvider = new-object System.Security.Cryptography.SHA512CryptoServiceProvider 
				Write-Log -DebugEntry ("Settings for algorithm: $HashfileEnding applied!")
			}
			catch { 
				Write-Log -DebugEntry ("Settings for algorithm: $HashfileEnding failed!")
				Write-Error -Message "SHA256 seems not to work on this system..." 
			}
			break
		} 
		default { 
			$HashfileEnding = "sha"
			$CProvider = new-object System.Security.Cryptography.SHA1CryptoServiceProvider
			Write-Log -DebugEntry ("Settings for algorithm: $HashfileEnding applied!")
		}
	} 
	# Fail back ‎algorithm
	if ($CProvider.HashSize -ne $ExpectedHashSize) {
		$CProvider = new-object System.Security.Cryptography.SHA1CryptoServiceProvider
		Write-Warning -Message "Failing back to SHA1 hash algorithm..."
		Write-Log -DebugEntry ("Failing back to SHA1 hash algorithm")
	}
	Write-Log -Entry ("Hash algorithm used: $HashfileEnding")
	### USER INTERFACE
	Write-Host -ForegroundColor Green "Hash algorithm used: " -NoNewline
	Write-Host $HashfileEnding
	
} 


##------------------------------------------------------------------------------------------------
## Main block
##------------------------------------------------------------------------------------------------
process { 
	#------------------------------------------------------------------------------------------------
	# Retrieve files in InputDirectory
	#------------------------------------------------------------------------------------------------
	$AllFilesName = "AllFilesHash"
	$FileList = @()
	# When removing existing hash files (default)
	if ($RemoveExistingHashFiles) {
		$FileList = Get-ChildItem -Path $InputPath -Filter $InputFileMask -Recurse | Where-Object {$_.PSIsContainer -eq $false -and $_.Extension -ne ("."+$HashfileEnding)} | Select-Object FullName, CreationTime, FileHash
	}
	# When keeping existing hash files
	else {
		$FileList = Get-ChildItem -Path $InputPath -Filter $InputFileMask -Recurse | Where-Object {$_.PSIsContainer -eq $false} | Select-Object FullName, CreationTime, FileHash
	}
	
	#------------------------------------------------------------------------------------------------
	# Verify there is something to archive
	#------------------------------------------------------------------------------------------------
	$FileCount = $FileList | Measure-Object | Select-Object -ExpandProperty Count
	if ($FileCount -eq $null) {
			Write-Warning "No file to archive..."
			Write-Log -Entry "[INFO] No file to archive..." -DebugEntry "in source"
			exit
	}
	
	#------------------------------------------------------------------------------------------------
	# Remove files that do not match file age criteria
	#------------------------------------------------------------------------------------------------
	$TempFileList = @()
	if ($InputMinFileAgeDays -ne 0) {
		Write-Log -Entry "Sorting out files that do not match file age criteria"
		$Progress = 1
		$FileList | foreach {
			Write-Progress -Activity "Adding files to list" -CurrentOperation ("Processing file: $Progress of $FileCount ("+$_.FullName+")") -PercentComplete ($Progress / $FileCount * 100) -Status "working"
			Write-Log -DebugEntry ("File:" +$_.FullName +" "+$_.CreationTime.Date)
			# If file age matches add it to the include file
			if ($_.CreationTime.Date -lt $ArchiveFilesOlderThen) {
				Add-FileToIncludeFile $_.FullName
				$TempFileList += $_
			}
		}
	}
	else {
		$FileList | foreach {
			Add-FileToIncludeFile $_.FullName
			$TempFileList += $_
		}
	}
	$FileList = $TempFileList
	$FileCount = $FileList | Measure-Object | Select-Object -ExpandProperty Count
	Write-Progress -Activity "Adding files to list" -Completed -Status "complete"
	
	#------------------------------------------------------------------------------------------------
	# Verify again if there is still something to archive
	#------------------------------------------------------------------------------------------------
	if ($FileCount -eq $null) {
		Write-Error "No file to archive..."
		Write-Log -Entry "No file to archive..." -DebugEntry "after exclusion handling"
		exit
	}
		
	##------------------------------------------------------------------------------------------------
	## Create hashes for selected files and create hash files
	##------------------------------------------------------------------------------------------------
	if ($CreateHashForAllFiles -or $CreateHashForEachFile) {
		#------------------------------------------------------------------------------------------------
		# Create hashes
		$Progress = 1
		$FileList | foreach {
			Write-Progress -Activity "Creating file hashes" -CurrentOperation ("Processing file $Progress of $FileCount ("+$_.FullName+")") -PercentComplete ($Progress / $FileCount * 100) -Status "working"
			$Progress++
			Write-Log -DebugEntry ("Creating hash for: "+$_.FullName)
			$_.FileHash = Create-FileHash -Filename $_.FullName -HashAlgorithm $HashAlgorithm
			$_.FullName = ($_.FullName.ToLower()).Replace($InputPath, "")
			Write-Log -DebugEntry ("Hash for: "+$_.FullName+"	"+$_.FileHash)
		}
		Write-Progress -Activity "Creating file hashes" -Completed -Status "complete"
		
		#------------------------------------------------------------------------------------------------
		# Create combined file with all hashes
		if ($CreateHashForAllFiles) {
			if ((Split-Path -Path $InputPath -Leaf) -ne $InputPath) {
				$AllFilesName = Split-Path -Path $InputPath -Leaf
			}
			$HashFileName = ($InputPath+$AllFilesName+"."+$HashfileEnding)
			Write-Log -Entry "Creating one hash file for all files" -DebugEntry ("FileName: "+ $HashFileName)
			if (Test-Path -Path $HashFileName) {
				Write-Log -Entry "Removing existing hash file!"
				$null = Remove-Item -Path $HashFileName -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
			}
			try {
				$Progress = 1
				$FileList | foreach {
					Write-Progress -Activity "Writing hashes to overall hash file" -CurrentOperation ("Processing hash: $Progress of $FileCount ("+$_.FullName+")") -PercentComplete ($Progress / $FileCount * 100) -Status "working"
					$Progress++
					Write-Log -DebugEntry ($_.FullName+" "+$_.FileHash)
					Add-Content -Path $HashFileName -Value ($_.FileHash+" "+$_.FullName)
				}
				#Include overall hash file to archive
				Add-FileToIncludeFile -FilePath $HashFileName
			}
			catch {}
		}
		
		#------------------------------------------------------------------------------------------------
		#Create individual hash file
		if ($CreateHashForEachFile) {
			Write-Log -Entry "Creating individual hash files..."
			try {
				$Progress = 1
				$FileList | foreach {
					Write-Progress -Activity "Writing hashes to hash files" -CurrentOperation ("Processing hash file: $Progress of $FileCount ("+$_.FullName+"."+$HashfileEnding+")") -PercentComplete ($Progress / $FileCount * 100) -Status "working"
					$Progress++
					$HashFileName = ($InputPath+$_.FullName+"."+$HashfileEnding)
					Write-Log -DebugEntry ($HashFileName+" "+$_.FileHash)
					if ($RemoveExistingHashFiles -and (Test-Path -Path $HashFileName)) {
						Write-Log -Entry "Removing existing hash file: $HashFileName"
						$null = Remove-Item -Path $HashFileName -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
					}
					Add-Content -Path $HashFileName -Value ($_.FileHash+" "+(Split-Path -Path $_.FullName -Leaf))
					#Include hash file to archive
					Add-FileToIncludeFile -FilePath $HashFileName
				}
			}
			catch {}
		}
	}
	Write-Progress -Activity "Writing hashes to hash files" -Completed -Status "complete"
	
	##------------------------------------------------------------------------------------------------
	## Archive files
	##------------------------------------------------------------------------------------------------
	$Progress = 1
	Write-Log -Entry "Adding files to archive..."
	
	### USER INTERFACE
	Write-Host -ForegroundColor Green "Adding files to archive..." 
	#------------------------------------------------------------------------------------------------
	# Test if IcludeList is present
	$TempFolder = Split-Path -Path $ArchiveFileName -Parent
	if (Test-Path -Path $IncludeListFileName) {
		$IncludeListCommand = "-i@$IncludeListFileName"
	}
	try {
		$null = .$SevenZipExecutablePath $SevenZipParameters "-w$TempFolder" $IncludeListCommand "$ArchiveFileName"
		Remove-IncludeListFile
	}
	catch {
		Write-Error "[ERROR] while archiving files"
		Write-Log -Entry "[ERROR] while archiving files"
		exit
	}
		
	#------------------------------------------------------------------------------------------------
	# Create hash on archive file
	if ($CreateArchiveHash) {
		Write-Log -Entry "Creating hash file for the archive..." -DebugEntry $ArchiveFileName
		if ($RemoveExistingHashFiles -and (Test-Path -Path ($ArchiveFileName+"."+$HashfileEnding))) {
			Write-Log -Entry ("Removing existing hash file: "+$ArchiveFileName+"."+$HashfileEnding)
			$null = Remove-Item -Path ($ArchiveFileName+"."+$HashfileEnding) -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
		}			
		Add-Content -Path ($ArchiveFileName+"."+$HashfileEnding) -Value ((Create-FileHash -Filename $ArchiveFileName -HashAlgorithm $HashAlgorithm)+" "+($ArchiveFileName))
	}


	##------------------------------------------------------------------------------------------------
	## Delete source files and folders
	##------------------------------------------------------------------------------------------------
	if ($DeleteSourceFiles) {
		Write-Log -Entry "Deleting archived of source files..."
		$FileCount = $FileList | Measure-Object | Select-Object -ExpandProperty Count
		$Progress = 1
		
		#------------------------------------------------------------------------------------------------
		# Delete processed files
		$FileList | foreach {
			Write-Progress -Activity "Deleting archived source files" -CurrentOperation ("file: $Progress of $FileCount ("+$_.FullName+")") -PercentComplete ($Progress / $FileCount * 100) -Status "working"
			$Progress++
				
			$HashFileName = ($InputPath+$_.FullName+"."+$HashfileEnding)
			$FileName = $InputPath+$_.FullName
				
			Write-Log -DebugEntry ("Deleting File: $HashFileName")
			Write-Log -DebugEntry ("Deleting File: $FileName")
			try {
				$null = Remove-Item -Path $HashFileName -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
			}
			catch {
				Write-Log -Entry ("[ERROR] Deleting file: $HashFileName")
			}
			try {
				$null = Remove-Item -Path $FileName -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
			}
			catch {
				Write-Log -Entry ("[ERROR] Deleting file: $FileName")
			}
		}
		
		#------------------------------------------------------------------------------------------------
		# Clean overall hash file
		if ($CreateHashForAllFiles) {
			Write-Log -DebugEntry ("Deleting File: $HashFileName")
			try {
				$HashFileName = ($InputPath+$AllFilesName+"."+$HashfileEnding)
				$null = Remove-Item -Path $HashFileName -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
			}
			catch {
				Write-Log -Entry ("[ERROR] Deleting file: $HashFileName")
			}
		}

		#------------------------------------------------------------------------------------------------		
		# Clean empty folders
		if ($DeleteEmptyFolders) {
			Write-Log -Entry "Deleting empty folders inside InputFolder..."
			$continue = $true
			while ($continue) {
				$continue = $false
				$EmptyFolders = (Get-ChildItem $InputPath -Recurse | Where-Object {$_.PSIsContainer -eq $True}) | Where-Object {$_.GetFiles().Count -eq 0 -and $_.GetDirectories().Count -eq 0} | Select-Object -Property FullName | Sort-Object -Descending
				$EmptyFolders | foreach {
					try {
						$FolderName = $_.FullName
						Write-Log -DebugEntry ("Deleting empty folder: $FolderName")
						$null = Remove-Item -Path $FolderName -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
						$continue = $true
					}
					catch {
						Write-Log -Entry ("[ERROR] Deleting empty folder: $HashFileName")
					}
				}
			}
			if ((Get-Item -Path $InputPath).GetFiles().Count -eq 0 -and (Get-Item -Path $InputPath).GetDirectories().Count){
				Write-Log -DebugEntry ("Deleting empty input folder: $InputPath")
				$null = Remove-Item -Path $InputPath -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
			}
		}
	}
	
	#------------------------------------------------------------------------------------------------		
	# Finished
	Write-Log -Entry "Operation finished! Script will end now." -DebugEntry (Get-Date)
} 

	


Download the script:

>> Version 1.0.3 (current)
(MD5: 17f6b9c18ed448b16716218b514dd751)
(SHA1: eaf97caa14b1fb27c5d435e45aae125cf728eb7a)


>> syntax highlighting powered by highlight.js