functions/Copy-ItemFiltered.ps1
function Copy-ItemFiltered { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string] $SourceDir, [Parameter(Mandatory=$true)] [string] $TargetDir, [switch] $Force, [string[]] $Excludes, $message = "Copying items..." ) $SourceDir = (get-item $SourceDir).FullName $activity = "$message $sourcedir => $targetDir" try { import-module pathutils $Excludes = $Excludes | % { $_.replace("\","/") } $Excludes = $Excludes | % { if ($_.StartsWith("/")) { $_.substring(1) } else { $_ } } #$excludedDirs = $Excludes | where { $_ -match "\\*\\" } | foreach { $_.Replace("\","\\") } Write-Verbose "excludes: $excludes" if (!(test-path $targetdir)) { $null = New-Item -ItemType Directory $targetdir } Write-Progress $activity -Status "getting list of directories" #get directories (recursively) to copy $dirs = @(pathutils\Get-Listing -Path $SourceDir -Recursive -Excludes $excludes -Dirs) Write-Progress $activity -Status "preparing... ($($dirs.length) dirs)" Write-Verbose "dirs: $dirs" #create matching direcctory structure foreach( $d in $dirs ) { if ($d -eq $null) { continue } $fullname = $d.FullName if ($fullname -eq $null) { $fullname = $d.Name } Write-Verbose "d.name=$($d.Name) fullname=$fullname tmpPath=$tmpPath" $tmpPath = Join-Path $targetdir (Get-RelativePath $SourceDir $fullname) if (!(test-path $tmpPath)) { $null = New-Item -ItemType Directory -Path $tmpPath } } $items = $dirs $items += get-item $sourcedir <# #get top-level dirs $items += Get-Listing $SourceDir -Exclude $excludes -Recursive:$false -Dirs Write-Verbose "items: $items" foreach( $d in $dirs ) { if ($d -eq $null) { continue } Write-Progress $activity -Status "preparing... listing '$($d.name)'" $curItems = Get-Listing $($d.FullName) -Exclude $excludes -Recursive:$false -Dirs if ($curItems -ne $null) { $items += $curItems } } #> $i = 0 $items | foreach { $i++ Write-Progress -Activity $activity -Status " directory '$_' ($i/$($items.Length))" -PercentComplete ($i/[float]$($items.Length) * 100) $dir = $_ try { $dest = Join-Path $targetdir (Get-RelativePath $SourceDir $_.fullname) $files = get-childitem $($_.fullname) -File -Recurse:$false $j = 0 $files | % { $j++ Write-Progress -Activity $activity -Status " directory '$dir' ($i/$($items.Length)) | file $_ ($j/$($files.length)) ($($_.length)B)" -PercentComplete ($i/[float]$($items.Length) * 100) try { Copy-Item "$($_.fullname)" -Force:$Force -Destination $dest } catch { # replace exceptions with errors, so ErrorAction could take effect write-error $_ } } } catch [System.Exception] { write-host "failed to copy dir $dir : $($_.Exception)" } } } finally { write-progress -Activity $activity -completed } } |