20

I am using a PowerShell script to move some files around on some servers. I want to test if a file I am going to move already exists in the destination. Not just a file with the same name.

I thought

Compare-Object $File1 $File2
Should do it but no matter what the files are it always returns that they are the same eg.

InputObject           SideIndicator                              
-----------           -------------                              
D:\1.gif               =>                                         
D:\1.wma               <=    

Is there some other way to test if two files are identical?

kbrimington
  • 25,142
  • 5
  • 62
  • 74
zebidy
  • 215
  • 1
  • 2
  • 5
  • You can use DOS (within PS): `**fc.exe "file1" "file2"**` (Note: must be "fc.exe" as "fc" is "format-custom" in PowerShell.) This gives much less cryptic output. – Andrew Nov 18 '17 at 17:16

6 Answers6

29
(Get-FileHash $path1).Hash -eq (Get-FileHash $path2).Hash
aifrim
  • 555
  • 9
  • 20
Diou KF
  • 291
  • 1
  • 3
  • 2
  • 1
    Is this really better than a years old, accepted solution? – Nico Haase Jan 29 '18 at 10:13
  • 9
    Yes it is - in some cases. As @Jaykul says, `it depends on your definition of 'the same'`. Example: I have two files whose Name and LastWriteTime differ, but whose content is the same. This solution is the fastest and best way to compare the content of two files (better than `Get-Content` for memory-related reasons described above). – Stadem Oct 09 '18 at 01:02
13

I guess it's going to depend on your definition of "The same"

Compare-Object (ls Source\Test.*) (ls Dest\Test.*) -Property Name, Length, LastWriteTime

That will compare the actual FILE objects by name, length, and modified date. Adding -IncludeEqual will result in also showing ones that are the same in both places.

If you want to only copy files from "Source" which aren't the same in the "Destination" just do this:

Compare-Object (ls $Source) (ls $Destination) -Property Name, Length, LastWriteTime -passthru | 
Where { $_.PSParentPath -eq (gi $Source).PSPath } |
Copy-Item $Destination

DO NOT start writing scripts that get-content (as suggested by others) to do a file comparison -- you'd be loading everything into memory...

DO consider using robocopy (even though it's command-line syntax is dated). =Þ

Jaykul
  • 15,370
  • 8
  • 61
  • 70
7

You're just giving two strings to Compare-Object, you want the file contents:

Compare-Object (gc $File1) (gc $File2)

Also the output you're giving does not mean that the files are the same.

Joey
  • 344,408
  • 85
  • 689
  • 683
4

What's wrong with comp.exe or fc.exe? Just check the $? after calling them to see if the command succeeded or not.

Keith Hill
  • 194,368
  • 42
  • 353
  • 369
1
compare $file1 $file2 -includeequal -excludedifferent
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
mexyz
  • 27
  • 1
1

You can test the file contents for equality, given paths $path1 and $path2 like so:

[io.file]::ReadAllText($path1) -eq [io.file]::ReadAllText($path2)

... Though you may choose instead to compare results of the ::ReadAllBytes() method.

To be honest, I just use Robocopy, even from PowerShell, when I care about copying only changed-or-added files.

kbrimington
  • 25,142
  • 5
  • 62
  • 74
  • 1
    Yes I started down the Robocopy path but dioscovered it didnt meet my requirements unfortunatly. Obviously this is a common solutionas everything I found with Google seems to lead to RoboCopy. – zebidy Aug 17 '10 at 01:08
  • 1
    Just out of curiosity, in what way did Robocopy not meet your requirements? – kbrimington Aug 17 '10 at 01:38
  • Care with this method: you are loading 2 files completely into memory and then comparing them... = very memory demanding – Davor Josipovic Apr 07 '13 at 11:23