Learn about Windows PowerShell
Summary: Microsoft Scripting Guy Ed Wilson illustrates how to compare two folders by using Windows PowerShell.
Microsoft Scripting Guy Ed Wilson here. It is an absolutely beautiful day in Charlotte, North Carolina. The early morning rain gave way to a colorful rainbow.
My manager bought me a new laptop, and I have been busy working on it; installing software, copying files, and migrating settings. The old laptop will be paved, so it is important to ensure I get everything copied to the new laptop.
Most of the major things are automatically transferred, but there are always a few folders that seem to get left behind. This is especially true because I am still working while doing the migration, and there is always a danger of missing something.
In the past, I might write a script to compare two folders to ensure they are identical. However, with Windows PowerShell, I do not need to write a script. I can type a simple command to compare two folders.
For example, I use a folder named fso that is located directly off of the root of the C: drive as my scratch directory. I leave all kinds of stuff in that directory, including files that contains important sample scripts and sample text files, spreadsheets, and databases. I use these files when writing articles, teaching, or making presentations. This folder is shown in the following figure.
There is nothing vital in the folder, but it is useful to have those files, so I want to ensure I have a good copy of the folder. Also, I am not capable of quickly reading through a folder with 144 files to ensure nothing is missing. To compare two folders I perform the following steps:
Note Do not get hung up on whether the first folder should be the reference object or the difference object. The position of the folder in the two parameters determines the direction of the comparison arrows, but as long as you know which folder is difference or reference, you will be fine.
The code I type on my laptop is shown here:
$fso = Get-ChildItem -Recurse -path C:\fso
$fsoBU = Get-ChildItem -Recurse -path C:\fso_BackUp
Compare-Object -ReferenceObject $fso -DifferenceObject $fsoBU
The code and associated output are shown in the following figure. The output tells me that inputobject (this is the difference object parameter) is missing three files: a.txt, b.txt, and c.txt. I need to copy these three files to the c:\fso_backup folder.
Well, it is the weekend, and as you can see, it is a beautiful day. I am going to get back to work on my laptop. Hope you have an awesome weekend. See you tomorrow.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at email@example.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
The alias for Compare-Object is diff. For more details/info on this cmdlet see technet.microsoft.com/.../dd347568.aspx and technet.microsoft.com/.../ee156812.aspx
this is something that I usually do with a "real diff.exe" or my "totalcommander" which give me a list of different files. It's Ok to use powershell for that purpose and even for a more general purpose because we are not restricted to compare files ... it's all about objects!
But I'm afraid that we won't be able to use this technique comparing a large directory structure like a complete filesystem content which will give us hundreds of thousands of files! So ... if we restrict it to some thousand files it may work very well :-)
@Craig Lussier You are correct. Thank you for the links
@Klaus Schulte You are also correct. This is not going to be fast enough to work through thousands of files. What it IS good for is a simple comparison between two files. For example, I often will run a command against two servers, and then use Compare-Object to compare the output. This IS great to do when looking at the status of services between two "identical" servers for example.
Very useful, easy to use, thank you. I have a question, however.
Is it possible to show the full path of the compared items? Just showing the item names that are different works fine, but when comparing folders with many subfolders and files, it's a bit more time-consuming to actually find where the items are. The script above is telling me that they are different, and which ones are different, but not exactly where they are located.
Besides that, this works GREAT!
@Juan the arrow points to the "side" containing the unique file. Therefore, the three files are in the c:\fso folder, and not in the backup folder. The arrow points in the direction of the file. The reference object, c:\fso contains the three files. The difference object c:\fso_backup does not contain the files.
I'm comparing two folders on different servers to make sure they robo copied correctly. I'm getting errors on path too long exception.
@mark - why?
Robocopy does this internally and knows how to deal with long paths.
Thank you, sir. This was quite helpful. I used this method to verify that I copied all the files from a folder to a DVD disc. I'm beginning to appreciate the simplicity and capabilities of power shell.
To get to the full pathname, just step through the difference object items using for-each and examine item.FullName.
I forget to mention that you need to use the -Passthru parameter to actually get access to the directory items.
Neat trick, Ed. I am looking for a way to locate edited/added folders on my music drive, which is not on my local PC, but on a WD MyBookLive. I have the music share folder mapped to the Z drive, but the Get-ChildItem no habla Z drive:
PS C:\Users\Allison> $music = Get-ChildItem -Recurse -path Z:\Shared Music
Get-ChildItem : Cannot find path 'Z:\Shared' because it does not exist.
At line:1 char:23
+ $music = Get-ChildItem <<<< -Recurse -path Z:\Shared Music
+ CategoryInfo : ObjectNotFound: (Z:\Shared:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
I have found much of the 'FileCompare' freeware that's out there to be lacking, so thanks for this...
The Compare-Object will compare the "string" value of the 2 files. It might be more useful if use something like Compare-Object -ReferenceObject $fso -DifferenceObject $fsoBU -Property Name,LastWriteTime,Length
Maybe someone can help. Compare-Object is acting up when I try to compare a previously saved txt file containing the get-childitem output of a directory to that of a real-time call to get-childitem of the same directory (where no changes have been made).
It shows Name is changing when it clearly has not. Is it possible to compare a txt file containing get-childitem output to the output of a real-time call to get-childitem? Here is how I am attempting this: # $dir2.txt is a previously saved call to get-childitem
of C:\dir2\ # $dir2.txt contents should match the get-childitem output from $dir1 $dir2 = get-content C:\dir2.txt $dir1 = get-childitem -recurse C:\dir1\ Compare-Object $dir1 $dir2 -Property Name
I need to be able to compare a directory to a text file. I.E. *.txt includes a list (1.txt, 2.txt, 3.txt...n) whereby it checks a directory to ensure the files in the directory correlate to the names in the text file, culminating in a list such as
1.txt is PRESENT
2.txt is PRESENT
3.txt is ABSENT
4.txt is EXTRA
I am finding that simply using get-childitem of the directory, saving both the text file list to an array and the directory list, then comparing, does not give me the desired outcome.
This worked except I don't know which sub-folder the missing file is in. As there are hundreds of folders involved, this puts me back into hunt-and-peck mode....