I am trying to script to rename username folders, but some of the folders are named USERNAME_S11-121-121.... I want to verify path using test-path with wild cards and rename-item doesn't take wild cards.
Is there a way I can use test-path and rename-item with just username and exclude everything except username.
I don't know if test-path $path* is correct way of doing it?
Function Reset-Profile {
param(
[parameter(Mandatory = $true, Position = 0)]
[string] $UserName,
[parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
$Server
)
process{
$SelectedUser = $UserName
$randomNumber = Get-Random
Foreach($UserName in $Server){
$paths = #(
"\\$Server\c$\users\$SelectedUser" #local profile
"\\server01\users$\$SelectedUser", #roaming profile
"\\server02\usersupmprd$\$SelectedUser" #roaming profile
)
foreach ($path in $paths)
{
if(test-path $path or test-path $path*)
{
Rename-Item -path $path -NewName "$SelectedUser.$randomNumber"
break;
write-host profile renamed under $path to
$SelectedUser.$randomNumber
}
else{ write-host path not found}
}
}
}
}
Untested, but try this:
Function Reset-Profile {
[cmdletbinding()]
param(
[parameter(Mandatory = $true, Position = 0)]
[string] $UserName,
[parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[string[]] $Server
)
Process{
$randomNumber = Get-Random
ForEach($Host in $Server)
{
$paths = #("\\$Host\c$\users\$UserName", #local profile
"\\server01\users$\$UserName", #roaming profile
"\\server02\usersupmprd$\$UserName") #roaming profile
ForEach ($path in $paths)
{
if(test-path "$path")
{
$CurrentPath = Get-Item "$path"
}
elseif(test-path $path_*)
{
write-host $path
$CurrentPath = Get-Item "$($path)_*" #it's necessary to put $path_ in parenthesis otherwise it conflicts with some internal command and gets the path of the directory I am working in.
write-host $CurrentPath
}
else {
Write-Warning "Path not found"
}
if($CurrentPath.Count() -eq 1)
{
Rename-Item -Path $CurrentPath -NewName "$UserName.$randomNumber"
Write-Verbose "Profile renamed under $path to $UserName.$randomNumber"
} elseif ($CurrentPath.Count -gt 1) {
Write-Warning "Multiple matches for $path"
} else {
Write-Warning "Path $path not found"
}
}
}
}
}
Explanation:
Added [string[]] in front of $Server so that it explicitly accepts array input (as well as a single string).
Changed ForEach($Username in $Server) to ForEach($Host in $Server) and made use of $Host so that it loops through the servers correctly.
Uses Get-ChildItem $Path* to get any matching paths. Then checks if a single path has been returned, if it has then it will do the rename, if it's multiple
or if there was no match it will warn you as such.
Changed write-host to write-verbose which will require use of the -verbose switch to be seen. Write-host is an anti-pattern, particularly in a Function.
How to execute:
I suggest you run this as follows initially (because i've added [cmdletbinding()] at the top of your function it now supports -WhatIf and -Verbose which should pass in to the Rename-Item cmdlet and will show you what it does. If it looks right, simply remove -WhatIf:
Reset-Profile -Username TestUsername -Server Localhost -WhatIf -Verbose
Related
Working to configure a conversion script where replacements are done in files based on what is in the CSV file. Like a dictionary or lookup, rather than directly storing in the code.
i.e.
File1.txt
Jim
Tim
Jan
Greg
Mark
CSV File
DEV,UAT,PROD
John,Jimothy,Timothy
Jimothy,Frank,Karen
Jim,Max,Lisa
So if converting DEV > UAT file1.txt would replace Jim with Max:
Max
Tim
Jan
Greg
Mark
Below is where I'm at currently convertReferences.ps1
#Declare Function Library
. $PSScriptRoot\functionLibrary.ps1
#Get Variables
$global:Dictionary = Import-Csv -Path $PSScriptRoot\IDDictionary.csv
#Input Location
$InputLocation = Read-Host 'Enter Input Location' ['DEV/UAT']
If(!(test-path $PSScriptRoot\$InputLocation))
{
New-Item -ItemType Directory -Force -Path $PSScriptRoot\$InputLocation
}
#Get Output Location
$OutLocation = Read-Host 'Enter an Output Location' ['UAT/PROD']
If(!(test-path $PSScriptRoot\$OutLocation))
{
New-Item -ItemType Directory -Force -Path $PSScriptRoot\$OutLocation
}
#Call Function Convert-DEV
if ($InputLocation -eq 'DEV'){
$Files | convert-DEV -InputLocation $InputLocation -OutLocation $OutLocation}
else {Write-host "NO VALID INPUT DECLARED - PLEASE RUN AGAIN" -ForegroundColor RED
<# Action when all if and elseif conditions are false #>
}
The Function itself is below:
function convert-DEV {
[cmdletbinding()]
param(
#Input Path
[Parameter(Mandatory)]
[ValidateSet('DEV')]
[string]
$InputLocation,
#Files
[Parameter(Mandatory, ValueFromPipeline)]
[string]
$Files,
#Output Path
[parameter()]
[ValidateSet('UAT')]
[string]
$OutLocation
)
process{
Write-host "Replacing Variables in: " $Files -ForegroundColor Blue
$Staging = $Files
(Get-Content $Files | foreach {$_ -replace $Global:Dictionary.DEV , $Global:Dictionary.UAT}) |
Set-Content $Files
(Get-Content $Staging | foreach {Copy-Item -Path $Staging -Destination $PSScriptRoot\$OutLocation})
Write-host "UPDATED File has been copied to: " -ForegroundColor Red $PSScriptRoot\$OutLocation `n `n
}
}
Any thoughts on how to reach my desired output?
You can use this function to get you started, this is assuming the CSV and the File are placed in the same location:
$csv = Import-Csv .\ReferenceTable.csv
function Replace {
[cmdletbinding()]
param(
[Parameter(Mandatory, ValueFromPipeline)]
[string] $File,
[Parameter(Mandatory)]
[ValidateSet('DEV', 'UAT', 'PROD')]
[string] $InputLocation,
[Parameter(Mandatory)]
[ValidateSet('DEV', 'UAT', 'PROD')]
[string] $OutLocation,
[Parameter(Mandatory)]
[object[]] $ReferenceTable
)
begin {
$map = #{}
foreach($i in $ReferenceTable) {
$map[$i.$InputLocation] = $i.$OutLocation
}
}
process {
foreach($line in (Get-Content $File).Trim()) {
if($map.ContainsKey($line)) {
$map[$line]
continue
}
$line
}
}
}
Get-ChildItem .\File1.txt | Replace -InputLocation DEV -OutLocation UAT -ReferenceTable $csv
After some further work and the help from Santiago above I have the below which works as I wanted:
function Start-Replace {
[cmdletbinding()]
param(
[Parameter(Mandatory, ValueFromPipeline)]
[string] $File,
[Parameter(Mandatory)]
[ValidateSet('DEV','UAT','PROD')]
[string] $InputLocation,
[Parameter(Mandatory)]
[ValidateSet('DEV', 'UAT', 'PROD')]
[string] $OutLocation,
[Parameter(Mandatory)]
[object[]] $ReferenceTable
)
begin {
#Create Map Hashtable/array
$map = #{}
#For each row in Reference list select the value in the input column and add to map array. After match and add output column value to array
foreach($row in $ReferenceTable)
{
$map[$row.$InputLocation] = $row.$OutLocation
}
}
#Replace
process {
$outname = split-path $file -leaf
$input = Get-Content $file
Foreach ($key in $map.Keys) {
$input = $input.Replace($key, $map.$key)
}
Set-Content -Path $PSScriptRoot\$OutLocation\$outlocation-$outname -value $input
write-host $outlocation'-'$outname
}
}
Please bare in mind I am a complete novice when it comes to powershell.
I am looking for a code that helps compare my folders with their back up folders, that are backed up with robocopy. I need to produce a notification for the user providing details.
#Create the balloon tip notification
function ShowBalloonTipInfo
{
[CmdletBinding()]
param
(
[Parameter()]
$Text,
[Parameter()]
$Title,
#It must be 'None','Info','Warning','Error'
$Icon = 'Info'
)
Add-Type -AssemblyName System.Windows.Forms
#So your function would have to check whether there is already an icon that you can reuse. This is done by using a "shared variable", which really is a variable that has "script:" scope.
if ($script:balloonToolTip -eq $null)
{
#we will need to add the System.Windows.Forms assembly into our PowerShell session before we can make use of the NotifyIcon class.
$script:balloonToolTip = New-Object System.Windows.Forms.NotifyIcon
}
$path = Get-Process -id $pid | Select-Object -ExpandProperty Path
$balloonToolTip.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path)
$balloonToolTip.BalloonTipIcon = $Icon
$balloonToolTip.BalloonTipText = $Text
$balloonToolTip.BalloonTipTitle = $Title
$balloonToolTip.Visible = $true
#I thought to display the tool tip for one seconds so i used 2000 milliseconds when I call ShowBalloonTip.
$balloonToolTip.ShowBalloonTip(2000)
}
}
Thank you very much to #mhu for helping me fix the error message. I now get the correct balloon tip notification but it says there are 1414 files that are different between my documents and its mirror.
Refactored your code, hope this helps...
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
# Create the balloon tip notification
function Show-BalloonTipInfo
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String] $Text,
[String] $Title,
[ValidateSet('None','Info','Warning','Error')]
[String] $Icon = 'Info'
)
Add-Type -AssemblyName "System.Windows.Forms"
$path = Get-Process -Id $pid | Select-Object -ExpandProperty "Path"
$balloonToolTip = New-Object -TypeName "System.Windows.Forms.NotifyIcon"
$balloonToolTip.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path)
$balloonToolTip.BalloonTipIcon = $Icon
$balloonToolTip.BalloonTipText = $Text
$balloonToolTip.BalloonTipTitle = $Title
$balloonToolTip.Visible = $true
#I thought to display the tool tip for one seconds so i used 2000 milliseconds when I call ShowBalloonTip.
$balloonToolTip.ShowBalloonTip(2000)
}
function Get-Directories
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String] $Path,
[Parameter(Mandatory = $true)]
[String] $Exclude
)
$pathLength = $Path.Length
if (Test-Path -Path $Path -PathType Container)
{
return Get-ChildItem -Path $Path -Recurse -Exclude $Exclude -File -ErrorAction SilentlyContinue |
Foreach-Object { $_.FullName.Substring($pathLength + 1) } |
Sort-Object
}
}
function Write-Log
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String] $Message,
[Parameter(Mandatory = $true)]
[String] $Path
)
$timestamp = Get-Date -format "dd-MM-yyyy HH:mm:ss"
$text = "$($timestamp): $message"
Write-Information -MessageData $text -InformationAction Continue
Add-Content -Path $Path -Value $text -Force -Encoding utf8
}
$logFile = "$env:Temp\sync.log"
# get content count
$folders = #(
#{ "Path" = [Environment]::GetFolderPath("MyDocuments"); "Exclude" = "*.pst,*.ost,*.iso"; "Files" = #() },
#{ "Path" = "D:\Documents_mirror"; "Exclude" = "*.pst,*.ost,*.iso"; "Files" = #() },
#{ "Path" = [Environment]::GetFolderPath("Desktop"); "Exclude" = "*.pst,*.ost,*.iso,*.lnk"; "Files" = #() },
#{ "Path" = "D:\Desktop_mirror"; "Exclude" = "*.pst,*.ost,*.iso,*.lnk"; "Files" = #() }
)
foreach ($folder in $folders)
{
Write-Log -Message "Searching for files in '$($folder.Path)'..." -Path $logFile
$folder.Files = #(Get-Directories -Path $folder.Path -Exclude $folder.Exclude)
}
Write-Log -Message "Comparing..." -Path $logFile
$documentsDiffCount = #(Compare-Object -ReferenceObject $folders[0].Files -DifferenceObject $folders[1].Files).Count
$desktopDiffCount = #(Compare-Object -ReferenceObject $folders[2].Files -DifferenceObject $folders[3].Files).Count
$message = ""
if (($documentsDiffCount -ge 1) -and ($documentsDiffCount -ge 1))
{
$message = "There are $documentsDiffCount file(s) in your documents and $desktopDiffCount file(s) on your desktop "
}
elseif ($documentsDiffCount -ge 1)
{
$message = "There are $documentsDiffCount file(s) in your documents "
}
elseif ($documentsDiffCount -ge 1)
{
$message = "There are $desktopDiffCount file(s) on your desktop "
}
if ($message)
{
$message += "that were not backed up. Please open robocopy and click 'Run Profile'"
}
else
{
$message = "Your files have been successfully backed up."
}
Write-Log -Message "Compare result: $message" -Path $logFile
Show-BalloonTipInfo -Text "Back up: $message"
Quick question regarding the PowerShell Copy-Item command. I was wondering if you have a directory structure and wanted to overwrite another directory structure is there a way to run the Copy-Item command in a 'preview' mode. It would output what files its overwriting from directory a to directory b but not actually perform the Copy-Item command.
Any help or advice appreciated.
Thanks.
Interesting question!
Here is my attempt of doing it all in Powershell, so not needing RoboCopy.
function Copy-Preview {
[CmdletBinding(DefaultParameterSetName = 'ByPath')]
param(
[Parameter(ValueFromPipeline = $true, Mandatory = $true, ParameterSetName = 'ByPath', Position = 0)]
[ValidateScript({ Test-Path $_ })]
[string]$Path,
[Parameter(ValueFromPipeline = $true, Mandatory = $true, ParameterSetName = 'ByLiteralPath', Position = 0)]
[ValidateScript({ Test-Path $_ })]
[string]$LiteralPath,
[Parameter(ValueFromPipeline = $true, Mandatory = $true, Position = 1)]
[string]$Destination,
[string]$Filter = $null,
[string]$Include = $null,
[string]$Exclude = $null,
[switch]$Recurse,
[switch]$Force
)
if ($PSCmdlet.ParameterSetName -eq 'ByLiteralPath') { $Path = $LiteralPath }
# determine if $Path and $Destination hold a file or a directory
$srcIsFolder = (Test-Path $Path -PathType Container -ErrorAction SilentlyContinue)
# cannot use Test-Path here because then the path has to exist.
# assume if it has an extension the path is a file, otherwise a directory
# NOTE:
# This is certainly not fullproof, so to avoid problems, always make sure
# the destination ends with a backslash if a directory is intended.
$destIsFolder = (-not ([System.IO.Path]::HasExtension($Destination)))
if ($destIsFolder -and !(Test-Path $Destination -PathType Container)) {
Write-Host "Destination path does not exist yet. All files from '$Path' will be copied fresh" -ForegroundColor Green
return
}
elseif ($srcIsFolder -and (!$destIsFolder)) {
# should not happen: source is a directory, while the destination is a file..
Write-Error "When parameter Path points to a directory, the Destination cannot be a file.."
return
}
$count = 0
if ($srcIsFolder -and $destIsFolder) {
# Both the source and the destinations are folders
# make sure both paths are qualified for .Replace() further down
if (-not $Path.EndsWith("\")) { $Path += "\" }
if (-not $Destination.EndsWith("\")) { $Destination += "\" }
$splat = #{
Filter = $Filter
Include = $Include
Exclude = $Exclude
Recurse = $Recurse
Force = $Force
}
# add either Path or LiteralPath to the parameters as they are mutually exclusive
if ($PSCmdlet.ParameterSetName -eq 'ByPath') { $splat.Path = $Path }
else { $splat.LiteralPath = $LiteralPath }
$srcFiles = Get-ChildItem #splat | Select-Object -ExpandProperty FullName
# reuse the splat parameters hash for the destination, but change the Path
if ($splat.LiteralPath) {($splat.Remove("LiteralPath"))}
$splat.Path = $Destination
$destFiles = Get-ChildItem #splat | Select-Object -ExpandProperty FullName
foreach ($srcItem in $srcFiles) {
$destItem = $srcItem.Replace($Path, $Destination)
if ($destFiles -contains $destItem) {
Write-Host "'$destItem' would be overwritten"
$count++
}
}
}
elseif (!$srcIsFolder) {
# the source is a file
if (!$destIsFolder) {
# the destination is also a file
if (Test-Path $Destination -PathType Leaf) {
Write-Host "'$Destination' would be overwritten"
$count++
}
}
else {
# source is file, destination is a directory
$destItem = Join-Path $Destination (Split-Path $Path -Leaf)
if (Test-Path $destItem -PathType Leaf) {
Write-Host "'$destItem' would be overwritten"
$count++
}
}
}
$msg = "$count item{0} would be overwritten by Copy-Item" -f $(if ($count -ne 1) { 's' })
$dash = "-" * ($msg.Length)
Write-Host "$dash`r`n$msg" -ForegroundColor Green
}
tl;dr:
Copy-Item -WhatIf will not give you the level of detail you're looking for - see below.
Use robocopy.exe -l instead (Windows only), as Ansgar Wiechers recommends, because it individually lists what files would be copied, including dynamically omitting those already present in the target dir (with the same size and last-modified time stamp, by default).
Generally, robocopy is faster and more fully featured than Copy-Item, and it avoids a notable pitfall of the latter.
Get-Help about_CommonParameters documents the -WhatIf common parameter supported by many (but not all) cmdlets, whose purpose is to preview an operation without actually performing it.
However, this feature is implemented in an abstract fashion, and often doesn't provide information as detailed as one would hope.
Case in point: while Copy-Item does support -WhatIf, it probably won't give you the level of detail you're looking for, because if the source item is a directory, only a single line such as the following is output:
What if: Performing the operation "Copy Directory" on target "Item: sourceDir Destination: destDir".
Note that you'll see the same line whether or not your Copy-Item call includes the -Recurse switch.
Even if you ensure existence of the target directory manually and append /* to the source directory path in order to see individual filenames, you'd only see them at the child level, not further down the subtree, and you'd never get the dynamic information that robocopy -l provides with respect to what files actually need replacement.
You can use the -whatif parameter.
Copy-item -path myfile.txt -destination myfoldertoCopyTo\ -whatif
I am new to powershell. I create a powershell script which need to search a string in the path provided in parameters and replace that string. But actually it is replacing entire file content with new string.
I am using Powershell in Windows 10 OS.
Code:
param(
[Parameter(Mandatory=$true, ParameterSetName="Path", Position=0,HelpMessage='Data folder Path')]
[string] $Path,
[Parameter(Mandatory=$true, HelpMessage='Input the string to be replaced')]
[string] $Input,
[Parameter(Mandatory=$true,HelpMessage='Input the new string that need to be replaced')]
[string] $Replace
)
$a = Test-Path $Path
IF ($a -eq $True) {Write-Host "Path Exists"} ELSE {Write-Host "Path Doesnot exits"}
$configFiles = Get-ChildItem -Path $Path -include *.pro, *.rux -recurse
$Append = join-path -path $path \*
$b = test-path $Append -include *.pro, *.rux
If($b -eq $True) {
foreach ($file in $configFiles)
{
(Get-Content $file.PSPath) |
Foreach-Object { $_ -replace [regex]::Escape($Input), $Replace } |
Set-Content $file.PSPath
}
$wshell = New-Object -ComObject Wscript.Shell
$wshell.Popup("Operation Completed",0,"Done",0x0)
}
As best I can read this without directly reproducing it, this is where it goes wrong:
(get-content $file.pspath) gets the entire content of the file, not its name.
Your "foreach" then regexes every line in the file, and finally "set-content" replaces the contents of the file, not its path.
If you want to change the name of a file, you are looking for Rename-Item, not Set-Content. If you want the name of a file $file.Name will do, you don't need Get-Content, which will ... get its content :)
This should be a working solution.
Param(
[Parameter(Mandatory,
ParameterSetName='Path',
Position=0,
HelpMessage='Data folder Path')]
[String]
$Path,
[Parameter(Mandatory,
HelpMessage='Input the string to be replaced')]
[String]
$StringToReplace,
[Parameter(Mandatory,
HelpMessage='Input the new string that need to be replaced')]
[String]
$ReplacementString
)
If (!(Test-Path $Path)) {
Write-Host 'Path does not exist'
Return
}
Get-ChildItem -Path $Path -Include *.pro,*.rux -Recurse |
? { $_.Name -like "*$StringToReplace*" } |
% { Rename-Item $_ $($ReplacementString+$_.Extension) }
(New-Object -ComObject Wscript.Shell).Popup("Operation Completed",0,"Done",0x0)
I am a newbie in PowerShell, and trying to learn the things from few forums and msdn. Now i got some requirement from my group of learners.
I am trying to compare 2 folder's files with each other in powershell, for effective file comparison i am using MD5 Hashes.
Till now i have created a code like this,
[Cmdletbinding()]
Param
(
[Parameter(Position=0, Mandatory)][ValidateScript({ Test-Path -Path $_ })][string]$SourceFolder,
[Parameter(Position=1, Mandatory)][ValidateScript({ Test-Path -Path $_ })][string]$DestinationFolder
)
$SourceFolderList =#()
$DestinationFolderList =#()
$Sourcefiles = #(Get-ChildItem -Path $SourceFolder -Filter *.log)
foreach($srcFile in $Sourcefiles )
{
$SourceFolderHash = [ordered]#{}
$SourceFolderHash.Name = $srcFile.Name
$SourceFolderHash.FullName = $srcFile.FullName
$obj = New-Object PSObject -Property $SourceFolderHash
$SourceFolderList+= $obj
}
$Destfiles = #(Get-ChildItem -Path $DestinationFolder -Filter *.log)
foreach($Destfile in $Destfiles )
{
$DestinationFolderHash = [ordered]#{}
$DestinationFolderHash.Name = $Destfile.Name
$DestinationFolderHash.FullName = $Destfile.FullName
$obj = New-Object PSObject -Property $DestinationFolderHash
$DestinationFolderList+= $obj
}
$SourceFolderList =#() &
$DestinationFolderList =#() are Arrays with Name & FullName properties.
Now i am trying to create a new array with values which matches in the $SourceFolderList & $DestinationFolderList ( I hope i am going in the right way?!)
But the problem is, i am not sure how to loop through each item in the Arrays and get the fullnames of each file from 2 folders to pass as params to MD5hash Function.
I am trying in this way
##1
For ($i =$j=0; $i -le $SourceFolderList.Count -and $j -le $DestinationFolderList.Count; $i++ -and $j++)
{
$file1Name = $SourceFolderList[$i].Name
$file1Path = $SourceFolderList[$i].FullName
$file2Name = $DestinationFolderList[$j].Name
$file2Path = $DestinationFolderList[$j].FullName
}
##2
foreach( $file in $SourceFolderList)
{
if($DestinationFolderList.Name -contains $file.Name )
{
Write-Host $file.Name -ForegroundColor Cyan
Write-Host $DestinationFolderList.($file.Name).FullName -ForegroundColor Yellow
}
}
In the 1st way i am not getting correct File Paths << Index is mismatching for Destination folder's file paths >>
In the 2nd Way i am not at all getting the Full Path of file.
Please correct me if am going in the wrong way to achieve my requirement.
And please help me to solve this issue.
I think your're making your task more difficult that it is, by gathering file info into the arrays. Why don't you just iterate over the files in the source folder and compare their hashes with hashes of files in the destination folder on the fly:
function Compare-Folders
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[string]$Source,
[Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
[string]$Destinaton,
[Parameter(ValueFromPipelineByPropertyName = $true)]
[string]$Filter
)
Process
{
# Iterate over files in source folder, skip folders
Get-ChildItem -Path $Source -Filter $Filter | Where-Object {!$_.PsIsContainer} | ForEach-Object {
# Generate file name in destination folder
$DstFileName = Resolve-Path -Path (Join-Path -Path $Destinaton -ChildPath (Split-Path -Path $_.FullName -Leaf))
# Create hashtable with filenames and hashes
$Result = #{
SourceFile = $_.FullName
SourceFileHash = (Get-FileHash -Path $_.FullName -Algorithm MD5).Hash
DestinationFile = $DstFileName
DestinationFileHash = (Get-FileHash -Path $DstFileName -Algorithm MD5).Hash
}
# Check if file hashes are equal and add result to hashtable
$Result.Add('IsEqual', ($Result.SourceFileHash -eq $Result.DestinationFileHash))
# Output PsObject from hashtable
New-Object -TypeName psobject -Property $Result |
Select-Object -Property SourceFile, SourceFileHash , DestinationFile, DestinationFileHash, IsEqual
}
}
}