Author Posts

January 1, 2012 at 12:00 am

by john808 at 2012-11-26 06:44:07

Hi,

I'd like to create a PS script that will compare two directories. Then, if one directory should contain a file the other doesn't, I would like that file to be copied to the other. Basically I want to make both directories identical.

I've been able to compare the directorires using the following:

$d1 = get-childitem -name -path "M:\Compare folder 1" $dir1 -recurse
$d2 = get-childitem -name -path "C:\Compare folder 2" $dir2 -recurse
compare-object $d1 $d2

This provides an output showing any differences but I would like to have the differences amended by copying the files.

Hopefully I've explained myself clearly. I'm a beginner so please feel free to tell me if this will be too complex for my currently level.

Thanks.

by DonJ at 2012-11-26 07:07:33

So... me, I'd probably just use Robocopy.exe for this ;). It's designed to sync directories and it's a lot faster.

But, if this is just a PowerShell exercise for you, you're on the right track. Assign the results of Compare-Object to a variable, say $result. Then try piping that to Get-Member. You'll see that the difference objects show you which "side" is different, and they contain the different objects.

So in your example, $d1 is left and $d2 is right. I might pass $result to Where-Object, keeping only those items which are on the left and not on the right (what's in $d1 that isn't in $d2). I'd then pipe *those* to Copy-Item or ForEach-Object to copy them from D1 to D2.

by john808 at 2013-04-30 06:24:15

Hi,

I've been working on this again but I'm having problems understanding "where-Object"? The part that is confusing is the syntax....

Here is the script I've been playng with...

[code2=powershell]# Setting variables
$Folder1 = Get-childitem M:\PSTestfolder1 -recurse
$Folder2 = Get-childitem M:\PSTestfolder2 -Recurse
$folder3 = M:\PSTestfolder3

Compare-Object -reference $Folder1 -difference $Folder2 | Where-Object {$_.name ***I'm stuck here*** } |

ForEach-Object {Copy-Item -Path $Folder1 ***this part doesn't look right*** -Destination $folder3}[/code2]

I'm sure the above is a bit messy and I'm going to continue working on it but thought I would ask for help to see what I get back.

Thanks for any assistance.

by DonJ at 2013-04-30 06:29:08

The output of Compare-Object is a difference object, not your original compared objects. Pipe Compare-Onject to GM and you'll see.

by john808 at 2013-05-01 02:20:03

So, below is my script that does what I wanted, almost. It compares two folders and copies any differences to a third folder. The problem is, when I run it, although the differences are copied to the third folder successfully, I get an error message for every item that is copied? I copied one of the error messages below the script. The error messages are all the same, the only difference is the file name.

[code2=powershell]# Setting variables
$Folder1 = Get-childitem "c:\PSTestfolder1" -Recurse
$Folder2 = Get-childitem "c:\PSTestfolder2" -Recurse

# Compare folders to see which objects are different.
Compare-Object -ReferenceObject $Folder1 -DifferenceObject $Folder2 -Property Name, Length |

# Results piped into Where-Object cmdlet to pick objects that are different on the left side.
Where-Object {$_.SideIndicator -eq "< ="}| # Then pipe result into ForEach-Object cmdlet, copy items to destination.
ForEach-Object {
Copy-Item "c:\PSTestfolder1\$($_.name)" -Destination "c:\PSTestfolder3" -recurse
}[/code2]

Error Message:
Copy-Item : Cannot find path 'C:\PSTestfolder1\Useful links.doc' because it does not exist.
At M:\Myscripts\Folder Compare Script.ps1:13 char:9
+ Copy-Item "c:\PSTestfolder1\$($_.name)" -Destination "c:\PSTestfolder3" ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\PSTestfolder1\Useful links.doc:String) [Copy-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand

I understand why the path can't be found, because as the message state, it does not exist. The actual path of the items is 'C]subfolder[/b]\Useful links.doc'. Where am I confusing my script and myself?

by ArtB0514 at 2013-05-01 05:40:34

One of the biggest problems people have with pipelines is understanding exactly what the $_ object is at any step. To see what you're feeding into the Copy-Item command (and to be able to choose the correct property), try this:

$Folder1 = Get-childitem "c:\PSTestfolder1" -Recurse
$Folder2 = Get-childitem "c:\PSTestfolder2" -Recurse
Compare-Object -ReferenceObject $Folder1 -DifferenceObject $Folder2 -Property Name, Length |
Where-Object {$_.SideIndicator -eq "< ="}| Select-Object -First 1 | Format-List *

Given that there's only one level of subfolder (and it always exists), you'll probably want to do something like this:
Copy-Item "c]
Or, you might find that this is what you want:
Copy-Item $_.FullName

by john808 at 2013-05-03 03:57:40

Hey art,

I tried your changes but they didn't seem to work. Using "Copy-Item "c]" gave me the same results, the files copy ok, but the same error message is recevied. If I try "Copy-Item $_.FullName" it fails with path errors, adding in a path then states invalid characters?

I've achived what I wanted by copying the files that are different between the two folders,but I was interested to know why I get errors.

Thanks for all the help.