It looks like you're relying on PS 2.0's behavior of having a $null value evaluating the .Length property on System.IO.DirectoryInfo, whereas when you run on PS 3/4 it's returning a '1'. If you need backward compatibility with PS 2.0, why not directly check the type in your where-object clause like this for your first statement filtering for Directories:
Where-Object { $_ -is [System.IO.DirectoryInfo] }
and then like this for your last statement targeting Files:
Where-Object { $_ -is [System.IO.FileInfo] }
This way you're not relying on properties who's behavior might change from version to version.
Full sample
function CopyWithFilterCommon ($sourcePath, $destPath)
{
$exclude = @('Thumbs.db' )
# Call this function again, using the child folders of the current source folder.
Get-ChildItem $sourcePath -Exclude $exclude | Where-Object { $_ -is [System.IO.DirectoryInfo] } | % { CopyWithFilterCommon $_.FullName (Join-Path -Path $destPath -ChildPath $_.Name) }
# Create the destination directory, if it does not already exist.
if (!(Test-Path $destPath)) { New-Item -Path $destPath -ItemType Directory | Out-Null }
# Copy the child files from source to destination.
Get-ChildItem $sourcePath -Exclude $exclude | Where-Object { $_ -is [System.IO.FileInfo] } | Copy-Item -Destination $destPath
Get-ChildItem -Path $sourcePath -Exclude $exclude | Where-Object { $_ -is [System.IO.FileInfo] } | % {
Copy-Item $_.FullName -Destination $destPath -Force
}
}