I am writing a PowerShell scripts that turns the following into a script that accepts 2 files as command line arguments, then outputs the difference of the two files to a text file.
Currently, my worthless code is as follows:
# Compare two text files passed as command line arguments
Function compareFiles()
{
Param (
[Parameter(mandatory=$true)]
[string]$file1,
[string]$file2
)
$file1 = resolve-path \.$file1
$file2 = resolve-path \.$file2
if ($file1 -eq $null) {
Write-Host "No source file."
}
if ($file2 -eq $null) {
Write-Host "No comparison file."
}
# Compare the two file objects
# => means $file2 has that line but not $file1
# =< means $file1 has that line but not $file2
# to see lines that arw the same, add -includeequal to end of the following line
Compare-Object -ReferenceObject (Get-Content $file1) -DifferenceObject (Get-Content $file2) | Out-File "$file1_$file2_Compare.txt" -Force
}
In a PowerShell console, the line Compare-Object -ReferenceObject (Get-Content $obj1) -DifferenceObject (Get-Content $obj2 works fine after defining $obj1="test1.txt" and $obj2="test2.txt".
When I run .\Compare-Files.ps1 -file1 test1.txt -file2 test2.txt from a PowerShell console, I get the following:
compareFiles : Cannot bind argument to parameter 'file1' because it is an empty string.
At C:\Users\debug255\Documents\Fiverr\PowerShell\Orders\armytra1n3d\FO4ADB39A404\Compare-Files.ps1:27 char:21
+ compareFiles -file1 $file1 -file2 $file2 | Out-File "$file1_$file2_Co ...
+ ~~~~~~
+ CategoryInfo : InvalidData: (:) [compareFiles], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,compareFiles
This error was resolved by removing the leftover $obj1 and $obj2 variables from earlier testing
This script from Hey Scripting Guy works fine
$fileA = "test1.txt"
$fileB = "test2.txt"
if(Compare-Object -ReferenceObject $(Get-Content $fileA) -DifferenceObject $(Get-Content $fileB))
{
"files are different"
}
Else
{
"Files are the same"
}
test1.txt contains the following:
test1
1
2
3
4
5
6
7
asaskjdahs
sl kasldk
test2.txt contains:
test2
1
23
3
4
5
6
799
asaskjdahs
sl kasldkJ
I am using PowerShell 5.1.14393.1066 on Windows 10.
Thank you for your help!
EDIT
I changed the script entirely so that there is no function for the comparison, and I used an example I found on GitHub for opening and comparing MS Word documents, which helped significantly.
# Compare two text files passed as command line arguments
Param (
[Parameter(mandatory=$true)]
$file1,
$file2
)
$ErrorActionPreference = 'Stop'
# Remove read-only attributes from baseFile
$baseFile = Get-ChildItem $file1
if ($baseFile.IsReadOnly) {
$baseFile.IsReadOnly = $false
}
try {
Compare-Object -ReferenceObject (Get-Content $file1) -DifferenceObject (Get-Content $file2) `
| Out-File $file1"_"$file2"_Comparison.txt" -Force
}
catch {
Write-Host "There was an error"
}
However, as soon as I wrap the code in a function, as compareFiles() { ... }, when I run the same line that did work without it being included in a function, .\Compare-Files.ps1 -file1 test1.txt -file2 test2.txt, nothing outputs. When I add a function call in the script below the function compareFiles, it then prompts me for $file1, the fails and does not prompt me for $file2, as it did before, just this time my catch caught it.
Then, I made the Param () global by placing them above the function compareFiles, and it worked!
Now, I need to focus on cleaning up with output a little bit. The output was as follows:
InputObject SideIndicator
----------- -------------
test2 =>
1 =>
23 =>
3 =>
4 =>
5 =>
6 =>
799 =>
asaskjdahs =>
sl kasldkJ =>
test1 <=
1 <=
2 <=
3 <=
4 <=
5 <=
6 <=
7 <=
asaskjdahs <=
sl kasldk <=
If any of you has any advise to make the output look something like:
test2.txt:
InputObject SideIndicator
----------- -------------
test2 =>
1 =>
23 =>
3 =>
4 =>
5 =>
6 =>
799 =>
asaskjdahs =>
sl kasldkJ =>
test1.txt
test1 <=
1 <=
2 <=
3 <=
4 <=
5 <=
6 <=
7 <=
asaskjdahs <=
sl kasldk <=
Also, I notice that it says that test1.txt has different content on lines 1, 2, 3, 4, etc, but they are actually the same (1 in test1.txt is the same and on the same line as test2.txt, for example).
Any advise for cleaning this up a bit?
Thank you all for your help!
Note: The question keeps changing and the code exhibits a variety of unrelated problems, so it's hard to give a meaningful answer, but here are a few pointers:
Param ( [Parameter(mandatory=$true)] $file1, $file2 )only defines$file1as mandatory, not also$file2- each parameter needs its own[Parameter(...)]attribute.\.$file1and\.$file2don't work the way you expect to; perhaps you meant.\$file1and.\$file2to refer to files in the current directory, but you don't need any prefix, becauseResolve-Pathdefaults to the current directory anyway.Tests
$file1 -eq $nulland$file2 -eq $nullwill never succeed, because$file1and$file2, due to having been declared[string]parameters, are never$null.[string]-typed variable in PowerShell defaults to the empty string rather than$null, and even explicitly assigning$nullresults in the empty string (compare that to C#, wherestringvariables default tonull, and assigningnullis possible).Expanding (interpolating) variables
$file1and$file2in string"$file1_$file2_Compare.txt"won't work, because, given that_is a legal character in a variable name, you must tell PowerShell where the variable names end, by enclosing them in{...}:"${file1}_${file2}_Compare.txt"