PowerShell : Copy Random Sample Files Script

<#
.SYNOPSIS
Takes a source path and copies a random sample of the files in each folder to a new destination, 
maintaining the folder structure.
.DESCRIPTION
Takes a source path and copies a random sample of the files in each folder to a new destination, 
maintaining the folder structure.  The files copied can be filtered.
.PARAMETER $SourcePath
The source directory to copy.
.PARAMETER $DestinationPath
The destination directory to copy to.
.PARAMETER $FileFilter
A simple filter to match the files to copy against.  Default is *.*
.PARAMETER $SampleNumber
The number of files to randomly take from each directory.  Default is 2.
.NOTES
Name : Copy-SampleFiles.ps1
Source : HerringsFishBait.com
#> 
[cmdletbinding()]
param
(
    [parameter(Mandatory=$true)]
    [ValidateScript({Test-Path $_ -PathType Container})]
    [string]$SourcePath,
    [parameter(Mandatory=$true)]
    [ValidateScript({Test-Path $_ -PathType Container -IsValid})]
    [string]$DestinationPath,
    [string]$FileFilter="*.*",
    [int]$SampleNumber=2
)
set-strictmode -version Latest

<#
.SYNOPSIS
Returns all the files within a passed directory.
.PARAMETER $DestinationPath
The destination directory to copy to.
.PARAMETER $FileFilter
A simple filter to match the files to copy against.  Default is *.*
.PARAMETER $SampleNumber
The number of files to randomly take from each directory.  Default is 2
#> 
function Get-SampleFiles
{
    param
    (
        [parameter(Mandatory=$true)]
        [System.IO.FileSystemInfo]$Directory,
        [parameter(Mandatory=$true)]
        [string]$FileFilter,
        [parameter(Mandatory=$true)]
        [int]$SampleNumber
    )
    Write-Verbose "Processing $($Directory.FullName)"
    Write-Verbose "Filter : $FileFilter, Sample Size : $SampleNumber"
    $Files=[array](Get-ChildItem -Path $Directory.FullName -Filter $FileFilter -File)
    $UsedNumbers=@()
    if ($Files -ne $Null)
    {
        if ($SampleNumber -le $Files.Count)
        {
            Write-Verbose "Getting Random Sample"
            $FilesToReturn=@()
            for ($i = 1; $i -le $SampleNumber; $i++)
            { 
                $NotFound=$True
                [int]$RandomChoice=0
                While($NotFound)
                {
                    $RandomChoice=Get-Random -Minimum 0 -Maximum $Files.Count
                    if(!($UsedNumbers -contains $RandomChoice))
                    {
                        $NotFound=$False
                        $UsedNumbers+=$RandomChoice
                    }
                }
                $FilesToReturn+=$Files[$RandomChoice]
            }
            Return $FilesToReturn
        }else
        {
            Write-Verbose "Not enough files for random sample.  Returning all files."
            Return $Files
        }
    }
    Write-Verbose "No Files returned."
    Return $Null
}
Write-Verbose "$((Get-Date).ToShortDateString()) : Started running $($MyInvocation.MyCommand)"
Write-Verbose "Source Path : $SourcePath"
Write-Verbose "Destination Path : $DestinationPath"
Write-Verbose "Getting folder list."
$Directories=Get-ChildItem $SourcePath -Directory -Recurse
Foreach ($Directory in $Directories)
{
    ForEach ($SampleFile in (Get-SampleFiles -Directory $Directory -FileFilter $FileFilter -SampleNumber $SampleNumber))
    {
        $FullSourcePath=$SampleFile.FullName
        $FullDestinationPath=$FullSourcePath -ireplace ([regex]::Escape($SourcePath),[regex]::Escape($DestinationPath))
        Write-Verbose "Copying $FullSourcePath to $FullDestinationPath"
        New-Item -Path $FullDestinationPath -Force
        Copy-Item -Force -Path $FullSourcePath -Destination $FullDestinationPath
    }
}