Reputation: 277
Someone kindly put together a powershell script for me. I'm a total amateur with programming. I haven't been able to reach this user to make a change that I'd like to to so I took it upon myself to modify the script myself.
Basically I want to pass an argument, two folder directories, so that the script can generate hash data from both source and destination and then compare them. The script works fine for that. But I want to check multiple sources and destinations.
I've done some googling and found that the following should work:
powershell.exe -Command 'C:\temp\hashcheck.ps1' -SourceDir "D:\Temp\Public" -DestDir "D:\Temp\Public2"
Where "sourcedir" and "destdir" are the names of the strings I want to pass. But when I run it from admin command prompt, it gives me error "unexpected token '-SourceDir'"
In the powershell script there are already a couple argument params but I added the "sourcedir" and "destdir" as follows:
param (
[Parameter(Mandatory=$True)]
[String]
$BaseDirectory,
[Parameter(Mandatory=$True)]
[String]
$SourceDir,
[Parameter(Mandatory=$True)]
[String]
$DestDir,
[Parameter(Mandatory=$True)]
[ValidateScript({!(Test-Path -path $_ -Type Leaf) })]
[String]
$OutputFilePath
)
and then pass that argument on in these commands:
# Run this for Source
Get-TreeCheckSum -BaseDirectory "$SourceDir" -OutputFilePath C:\temp\PublicSource.xml -Verbose
# Run this for Destination
Get-TreeCheckSum -BaseDirectory "$DestDir" -OutputFilePath C:\temp\PublicDestination.xml -Verbose
Thanks for any help. It's probably a simple solution, but as I said, I am complete amateur with powershell. Thanks in advance.
EDIT: Here's the full code, maybe will make more sense. I basically want to pass the folder name under "# Run this for source" and "#Run this for Destination" section assigned to "BaseDirectory"
# Created by P33500k for fun..
# Use at your own risk follow directions at end to run the commands
function Get-TreeCheckSum {
[CmdletBinding()]
param (
[Parameter(Mandatory=$True)]
[String]
$BaseDirectory,
[Parameter(Mandatory=$True)]
[ValidateScript({!(Test-Path -path $_ -Type Leaf) })]
[String]
$OutputFilePath
)
begin {
# Define $results as an array of objects
$results = @()
}
process {
Write-Verbose "Getting all files in $BaseDirectory..."
# check files
$allfiles = Get-ChildItem -path $BaseDirectory -Force -File -Recurse | select-object Name,FullName,Length
Write-Verbose "Found $($allfiles.count) files in $BaseDirectory..."
$n = 0
Foreach ($File in $allfiles) {
$n++
Write-Progress -Activity "CheckSumming $BaseFolder" -Status "Checksumming $($File.FullName)" -PercentComplete (($n / ($allfiles | measure-object | Select-object -ExpandProperty Count)) * 100)
Write-Verbose "Checksumming $($file.fullname)"
$tempobj = New-Object -TypeName psobject -Property @{
'FullPath' = $file.FullName
'FileName' = $file.Name
'Size' = $file.Length
'Hash' = (Get-FileHash -Path $file.fullname | select-object -ExpandProperty Hash)
'RelativePath' = ($file.fullname.substring($BaseDirectory.Length))
}
$results += $tempobj
$tempobj = $null
}
Write-Verbose "Hashing Complete for file set in $BaseDirectory"
}
end {
Write-Verbose "Writing Output File to $OutputFilePath"
$results | Export-Clixml -Path $OutputFilePath
}
}
# Run this for Source
Get-TreeCheckSum -BaseDirectory "D:\Temp\Public" -OutputFilePath C:\temp\PublicSource.xml -Verbose
# Run this for Destination
Get-TreeCheckSum -BaseDirectory "D:\Temp\Public2" -OutputFilePath C:\temp\PublicDestination.xml -Verbose
# Run this code for comparing
# Global variables for comparing
$Filesnotondestination = ".\FilesNotonDestination.txt"
$Filesnotonsource = ".\FilesNotonSource.txt"
$FailedHashes = ".\Failedchecksums.txt"
$Source = import-clixml C:\temp\PublicSource.xml
$Destination = import-clixml C:\temp\PublicDestination.xml
Write-Host "Comparing objects.."
$compare = Compare-Object -ReferenceObject $Source -DifferenceObject $Destination -Property RelativePath -IncludeEqual
Write-Host "Writing file names to files only on source.."
$compare | Where-object {$_.SideIndicator -eq "<="} | Select-object -expandproperty RelativePath | Set-content -path $Filesnotondestination
Write-Host "Writing file names to files only on destination.."
$compare | Where-object {$_.SideIndicator -eq "=>"} | Select-object -expandproperty RelativePath | Set-content -path $Filesnotonsource
Write-Host "Comparing files on both source and destination... "
$verify = $compare | Where-object {$_.SideIndicator -eq "=="}
Write-Host "Found $($verify.count) files that are in both paths.."
$n = 0
foreach ($v in $verify) {
$n++
Write-progress -Activity "Comparing file hashes.." -Status "Processing File: $($v.relativepath)" -PercentComplete (($n / ($verify | measure-object | Select-object -ExpandProperty Count)) * 100)
#Write-Host "Comparing $($v.relativepath).."
#Write-Host $v.relativepath
Foreach ($s in $source) {
If ($s.relativepath -eq $v.relativepath) {
$sourceh = $s.hash
#Write-Host "Source Hash: $Sourceh"
}
}
Foreach ($d in $Destination) {
If ($d.relativepath -eq $v.relativepath) {
$desth = $d.hash
#Write-Host "Destination Hash: $desth"
}
}
If ($desth -eq $sourceh) {
#Write-Host "File hashed match"
}
Else {
Write-Warning "$($v.relativepath) - File Hashes Do Not Match"
Add-content -path $FailedHashes -value "$(get-date) - $($v.relativepath) failed checksum: $sourceh not equal to $desth"
}
}
Upvotes: 2
Views: 665
Reputation: 15470
You don't want to call the BaseDirectory parameter. So, change the source ps1 script into
Param (
[string]$BaseDirectory,
# The Rest of the script
It will not ask for base directory as it is no longer mandatory.
Now call the script with the rest parameters.
Upvotes: 1
Reputation: 39
Try calling the script directly like this:
C:\temp\hashcheck.ps1 -SourceDir "D:\Temp\Public" -DestDir "D:\Temp\Public2"
Upvotes: 1