unlikely
unlikely

Reputation: 438

What is the cleanest way to join in one array the result of two or more calls to Get-ChildItem?

I'm facing the problem of moving and copying some items on the file system with PowerShell.

I know by experiments the fact that, even with PowerShell v3, the cmdlet Copy-Item, Move-Item and Delete-Item cannot handle correctly reparse point like junction and symbolic link, and can lead to disasters if used with switch -Recurse.

I want to prevent this evenience. I have to handle two or more folder each run, so I was thinking to something like this.

$Strings = @{ ... }
$ori = Get-ChildItem $OriginPath -Recurse
$dri = Get-ChildItem $DestinationPath -Recurse

$items = ($ori + $dri) | where { $_.Attributes -match 'ReparsePoint' }
if ($items.Length -gt 0)
{
    Write-Verbose ($Strings.LogExistingReparsePoint -f $items.Length)
    $items | foreach { Write-Verbose "    $($_.FullName)" }
    throw ($Strings.ErrorExistingReparsePoint -f $items.Length)
}

This doen't work because $ori and $dri can be also single items and not arrays: the op-Addition will fail. Changing to

$items = @(@($ori) + @($dri)) | where { $_.Attributes -match 'ReparsePoint' }

poses another problem because $ori and $dri can also be $null and I can end with an array containing $null. When piping the join resutl to Where-Object, again, I can end with a $null, a single item, or an array.

The only apparently working solution is the more complex code following

$items = $()
if ($ori -ne $null) { $items += @($ori) }
if ($dri -ne $null) { $items += @($dri) }
$items = $items | where { $_.Attributes -match 'ReparsePoint' }

if ($items -ne $null)
{
    Write-Verbose ($Strings.LogExistingReparsePoint -f @($items).Length)
    $items | foreach { Write-Verbose "    $($_.FullName)" }
    throw ($Strings.ErrorExistingReparsePoint -f @($items).Length)
}

There is some better approch?

I'm interested for sure if there is a way to handle reparse point with PowerShell cmdlets in the correct way, but I'm much more interested to know how to join and filters two or more "PowerShell collections".

I conclude observing that, at present, this feature of PowerShell, the "polymorphic array", doen't appear such a benefit to me.

Thanks for reading.

Upvotes: 2

Views: 508

Answers (2)

Justin Dunlap
Justin Dunlap

Reputation: 181

I've been on Powershell 3 for a while now but from what I can tell this should work in 2.0 as well:

$items = @($ori, $dri) | %{ $_ } | ? { $_.Attributes -match 'ReparsePoint' }

Basically %{ $_ } is a foreach loop that unrolls the inner arrays by iterating over them and passing each inner element ($_) down the pipeline. Nulls will automatically be excluded from the pipeline.

Upvotes: 0

DWright
DWright

Reputation: 9500

Just add a filter to throw out nulls. You're on the right track.

$items = @(@($ori) + @($dri)) | ? { $_ -ne $null }

Upvotes: 1

Related Questions