首页 > 解决方案 > 递归复制与模式匹配的文件

问题描述

我已经编写了一个脚本,该脚本以递归方式从一个目录复制到另一个目录,跳过文件名中具有特定模式的文件:

函数 Copy-RevitFiles ([string]$source, [string]$destination, [boolean]$recurse) {

    $pattern = '\.\d\d\d\d\.[RVT]'

    if ($recurse) {$files = Get-ChildItem $source -Recurse}
    否则 {$files = Get-ChildItem $source}


    $文件 | ForEach-对象 {
    if ((Select-String -InputObject $_.Name -pattern $pattern -AllMatches -quiet) -eq $null) {
        #Write-Host $_.Name
        #Write-Host $_.Fullname
        #Write-Host "$($destination)\$($_.FullName.TrimStart($source))"
        Copy-Item $_.FullName -Destination "$($destination)\$($_.FullName.TrimStart($source))" #add on the full name of item, less $source start end of file path
        #Write-Host "---------"
        }
    }
}

在大多数情况下,它运作良好。我遇到的问题是它在每个文件夹中创建了一个额外的子文件夹,其中包含文件。例如:

如果将源作为具有此结构的目录输入:

资源
-file1.rvt
-file1.0225.rvt(不会复制,因为它与模式匹配)
-file1.0226.rvt(不会复制,因为它与模式匹配)
-文件夹1
 |-file2.rvt
 |-file2.0121.rvt(不会复制,因为它与模式匹配)
 |-file2.0122.rvt(不会复制,因为它与模式匹配)
-文件夹2

我期望在目标文件夹中创建以下结构:

目的地
-file1.rvt
-文件夹1
 |-file2.rvt
-文件夹2

但相反,我得到:

目的地
-file1.rvt
-文件夹1
 |-file2.rvt
 |-folder1(不在源中的额外文件夹)
-文件夹2

知道我哪里出错了吗?

标签: powershell

解决方案


Select-STring这是您构建目标的方式,也是您如何使用 option 处理 cmdlet的返回值-Quiet
使用该Quiet开关将使 cmdlet 返回一个布尔值($true 或 $false),但您正在测试与$null.

如果我Join-Path像这样使用 cmdlet(以及对您的功能进行的一些其他调整):

function Copy-RevitFiles {
    [CmdletBinding()]
    Param(
        [string]$source, 
        [string]$destination,
        [string]$pattern, 
        [switch]$recurse
    )

    # test if the destination folder exists
    if (!(Test-Path -Path $destination -PathType Container)) {
        New-Item -ItemType Directory -Path $destination -Force | Out-Null
    }

    $files = Get-ChildItem $source -Recurse:$recurse

    $files | ForEach-Object {
    if (!(Select-String -InputObject $_.Name -Pattern $pattern -AllMatches -Quiet)) {
        #Write-Host $_.Name
        #Write-Host $_.Fullname
        $target = Join-Path -Path $destination -ChildPath $_.Fullname.TrimStart($source)
        #Write-Host "Copying '$_.Fullname' to '$target'" 
        $_ | Copy-Item -Destination $target
        #Write-Host "----------"
        }
    }
}

并根据您的Source示例使用它:

Copy-RevitFiles -source "D:\Source" -destination "D:\Destination" -pattern '\.\d\d\d\d\.[RVT]' -recurse

这将导致:

Destination
|   file1.rvt
|
+---folder1
|       file2.rvt
|
\---folder2

推荐阅读