Question

I have powershell script in 2.0 version (Windows 2008). But it's fails for me in PS 3.0 - 4.0 (Windows 2012). Fails because not get any files, when there are files.

And I have powershell script in 4.0 version (Windows 2012). But it's fails for me in PS 2.0 (Windows 2008). Fails because Directory switch isn't recognised.

The scripts contains files-folders copy functions.

This code for Powershell 2.0

function CopyWithFilterOlder ($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 { $_.Length -eq $null } | % { CopyWithFilterOlder $_.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 { $_.Length -ne $null } | Copy-Item -Destination $destPath
}

Now this code for Powershell 3.0 - 4.0

function CopyWithFilter ($sourcePath, $destPath)
{
    $exclude = @('Thumbs.db' )

    # Call this function again, using the child folders of the current source folder.
    Get-ChildItem $sourcePath -Directory -Exclude $exclude |  % { 
        CopyWithFilter $_.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 -File -Path $sourcePath | % { 
        Write-Host ("`t`t`tCopy {0} to {1}" -f $_.FullName,  $destPath); 
        Copy-Item $_.FullName -Destination $destPath -Force
    } 

}

I would like mantain the same code, independent from PS version.

Any suggestions about it?

Was it helpful?

Solution

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
    } 
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top