Find File Duplicates with PowerShell

I’ve recently been tasked with finding duplicate files across multiple shares on a network. I’ve looked at a few different free options out there that can do this and in the end found that PowerShell can do this for me, for free. Might want to grab a cup of coffee, or a pot, depending on how many directories and large files you have.
Get-DuplicateFiles.ps1

# USAGE:
# .Get-DuplicateFiles.ps1
param ([string] $Path = (Get-Location))
Add-Type -AssemblyName System
function Get-MD5 (
    [System.IO.FileInfo]
    $file = $(throw 'Usage: Get-MD5 [System.IO.FileInfo]')
) {
    # This Get-MD5 function sourced from:
    # http://blogs.msdn.com/powershell/archive/2006/04/25/583225.aspx
    $stream = $null
    $cryptoProvider = [System.Security.Cryptography.MD5CryptoServiceProvider];
    $hashAlgorithm = New-Object $cryptoProvider
    $stream = $file.OpenRead()
    $hashByteArray = $hashAlgorithm.ComputeHash($stream)
    $stream.Close()
    ## We have to be sure that we close the file stream if any exceptions are thrown.
    trap {
        if ($stream -ne $null) { $stream.Close() }
        break
    }
    return [string]$hashByteArray
}
$fileGroups = Get-ChildItem -Path $Path -Recurse |
    Where-Object { $_.Length -gt 0 } |
    Group-Object Length |
    Where-Object { $_.Count -gt 1 }
foreach ($fileGroup in $fileGroups) {
    foreach ($file in $fileGroup.Group) {
        Add-Member -MemberType NoteProperty -Name ContentHash -Value (Get-MD5 $file) -InputObject $file
    }
    $fileGroup.Group |
        Group-Object ContentHash |
        Where-Object { $_.Count -gt 1 }
}

Output Example

Count Name                      Group
----- ----                      -----
    2 187 49 165 178 166 151... {Ann-DS1.imr, Ann-DS1.imr}
    2 230 243 103 209 89 0 1... {MQ02 Mailing Labels Laser for Pat Birthday by Post Dates.imr, MQ02 Mailing Labels Laser for Pat Birthday by Post Dates.imr}
    2 129 199 76 16 247 255 ... {ANN-Folder-Subfolder Listing.imr, ANN-Folder-Subfolder Listing.imr}
    2 16 249 151 209 119 71 ... {Annotation Report.imr, Annotation Report.imr}
    2 114 146 127 255 123 23... {Annotation.mdb, Annotation.mdb}

Find Computer's Serial Number via Command Line

Here are a few methods to retrieve the computer’s serial number from the command line.

Using WMIC

wmic csproduct get IdentifyingNumber /format:list
wmic bios get SerialNumber /format:list

Using PowerShell (Call to WMI)

(Get-WmiObject -cl win32_BIOS).SerialNumber

HTML Application (HTA) Using VBScript

Get Serial Number HTA Screenshot
Get Serial Number HTA Screenshot

Download

A Simple PowerShell Windows du Implementation

I was looking for a quick and easy way to get directory and file size for a given directory and its sub-directories.  I came across a nice post by Luis Diego Fallus and ended up using a commenter’s code to produce output in MB format.

gci . | %{$f=$_; gci -r $_.FullName |
	measure-object -property length -sum |
		select @{Name="Name"; Expression={$f}} ,
		@{Name="Sum (MB)"; Expression={ "{0:N3}" -f ($_.sum / 1MB) }}, Sum } |
	sort Sum -desc | format-table -Property Name,"Sum (MB)" -autosize

Example Output

Name                  Sum (MB)
----                  --------
Adobe                 1,603.809
TestDirectory         67.715

Transparent Command, Putty, Powershell and PuTTY Windows

I modified the code from NothinButNet’s Glass project on CodePlex to run continuously and monitor for the following windows:
PuTTY (putty.exe)
Windows Command Prompt (cmd.exe)
Powershell (powershell.exe)
Telnet (telnet.exe)
There isn’t a way to stop it once started other than killing the task (taskkill /f /im glass.exe) or however you choose.
You can pass the original parameters to it still if you want by either a shortcut or however you want and it will work so you can set transparency level, etc. You can throw it in startup folder to start with Windows or whichever method you prefer.
Here’s a screenshot of default transparency (200):

Glass.exe – Running in background continously.

Download binary file here: Glass.zip
Download source here: glass-15166.01_source.zip

Powershell Active Directory Searcher Boiler Plate

I’m sure I’ll be using this more and more in the coming months as I familiarize myself with Powershell. Below is a template or boilerplate for Active Directory Searcher in Powershell. This was taken from a great video podcast from Youtube by David Hoelzer. Below is the video from Youtube. You can check out his channel for some other great videos.

Here’s the Powershell code.

$Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$ADSearch = New-Object System.DirectoryServices.DirectorySearcher
$ADSearch.SearchRoot = "LDAP://$Domain"
$ADSearch.SearchScope = "subtree"
$ADSearch.PageSize = 100
$ADSearch.Filter = "(objectClass=user)"
$ADSearch.PropertiesToLoad.Add("distinguishedName")
$ADSearch.PropertiesToLoad.Add("sAMAccountName")
$ADSearch.PropertiesToLoad.Add("lastLogonTimestamp")
$userObjects = $ADSearch.FindAll()
foreach ($user in $userObjects)
{
    $dn = $user.Properties.Item("distinguishedName")
    $sam = $user.Properties.Item("sAMAccountName")
    $logon = $user.Properties.Item("lastLogonTimeStamp")
    if($logon.count -eq 0)
    {
        $lastLogon = "Never"
    }
    else
    {
        $lastLogon = [DateTime]$logon[0]
        $lastLogon = $lastLogon.AddYears(1600)
    }
    """$dn"",$sam,$lastLogon"
}