Reputation: 438
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
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
Reputation: 9500
Just add a filter to throw out nulls. You're on the right track.
$items = @(@($ori) + @($dri)) | ? { $_ -ne $null }
Upvotes: 1