首页 > 解决方案 > 使用 csv 数据 powershell 时仅复制某些文件夹

问题描述

我不想复制所有文件夹如何告诉它不要复制某些文件夹,例如( appData 和 application Data )

csv 文件包含:

FullName                             Name
\\computer6587\c$\Users\A2846      A2846
\\computer6587\c$\Users\B2846      B2846

代码:

Import-Csv -path C:\computer6587-PREP.csv | foreach {Copy-item -recurse $_.FullName "c:\backup" -Force -Verbose}

标签: powershellcsvcopy

解决方案


为此,我前段时间做了一个辅助函数:

function Copy-ExcludeFolders {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [ValidateScript({ $_ | Test-Path -PathType Container })]
        [string]$SourceFolder,

        [Parameter(Mandatory = $true, Position = 1)]
        [string]$Destination,

        [Parameter(Mandatory = $true, Position = 2)]
        [string[]]$Exclude,

        [switch]$Force
    )

    # create a regex of the folders to exclude
    # each folder will be Regex Escaped and joined together with the OR symbol '|'
    $notThese = ($Exclude | ForEach-Object { [Regex]::Escape($_) }) -join '|'

    Get-ChildItem -Path $SourceFolder -Recurse -File |
         Where-Object{ $_.DirectoryName -notmatch $notThese } |
         ForEach-Object {
            $target = Join-Path -Path $Destination -ChildPath $_.DirectoryName.Substring($SourceFolder.Length)
            if (!(Test-Path -Path $target -PathType Container)) {
                Write-Verbose "Creating folder '$target'"
                $null = New-Item -Path $target -ItemType Directory
            }
            Write-Verbose "Copying '$($_.FullName)' to '$target'"
            $_ | Copy-Item -Destination $target -Force:$Force
         }
}

将该函数放在脚本顶部,像这样使用它:

$exclude = 'appData', 'application Data'  # add more folders to exclude here
Import-Csv -Path 'C:\computer6587-PREP.csv' | ForEach-Object {
    Copy-ExcludeFolders -SourceFolder $_.FullName -Destination 'C:\backup' -Exclude $exclude -Force -Verbose
}

如果您希望将用户数据复制到目标路径中的某个子文件夹,那么我建议您也使用Namecsv 中的列。

$exclude = 'appData', 'application Data'  # add more folders to exclude here
Import-Csv -Path 'C:\computer6587-PREP.csv' | ForEach-Object {
    $dest = Join-Path -Path $destination -ChildPath $_.Name
    # just to see if the input from the csv will give you the desired source and destination paths:
    Write-Host "Copying files from '$($_.FullName)' to folder '$dest'"
    Copy-ExcludeFolders -SourceFolder $_.FullName -Destination $dest -Exclude $exclude -Force -Verbose
}

编辑

我们不应该对一个问题添加这么多评论。这就是我测试上述代码的方式,结果表明它完全符合预期。

我用它来输入 csv 调用Source-PREP.csv(你的文件名当然会不同)

FullName,Name,LastWriteTime
D:\Test\Users\H107371a,H107371a,11/25/2020 7:19
D:\Test\Users\m763671,m763671,12/3/2020 9:12
D:\Test\Users\W575288,W575288,9/18/2020 15:23
D:\Test\Users\W575288a,W575288a,9/18/2020 15:23

然后我在我的 D:\Test 路径中创建了一些虚拟用户,其中包含“appData”和“应用程序数据”文件夹以及一些应该复制的子文件夹:

D:\TEST\USERS
+---H107371a
|   |   test.txt
|   |
|   +---appData
|   |       mustnotcopy.txt
|   |
|   +---application Data
|   |       donotcopy.txt
|   |
|   +---Folder1
|   |       blah.txt
|   |       somepicture.jpg
|   |
|   \---Folder2
|           myvideo.mp4
|           whatever.txt
|
+---m763671
|   |   test.txt
|   |
|   +---appData
|   |       mustnotcopy.txt
|   |
|   +---application Data
|   |       donotcopy.txt
|   |
|   +---FolderA
|   |       blah1.txt
|   |       somepicture1.jpg
|   |
|   \---FolderB
|           myvideo1.mp4
|           whatever1.txt
|
+---W575288
|   |   test.txt
|   |
|   +---appData
|   |       mustnotcopy.txt
|   |
|   +---application Data
|   |       donotcopy.txt
|   |
|   +---FolderX
|   |       blah2.txt
|   |       somepicture2.jpg
|   |
|   \---FolderY
|           myvideo2.mp4
|           whatever2.txt
|
\---W575288a
    |   test.txt
    |
    +---Another-Folder
    |       myvideo3.mp4
    |       whatever3.txt
    |
    +---appData
    |       mustnotcopy.txt
    |
    +---application Data
    |       donotcopy.txt
    |
    \---Some-Folder
            blah3.txt
            somepicture3.jpg

接下来,我运行代码

$exclude     = 'appData', 'application Data'  # add more folders to exclude here
$destination = "\\<myMachine>\D$\CopiedProfiles"

Import-Csv -Path 'D:\Source-PREP.csv' | ForEach-Object {
    $dest = Join-Path -Path $destination -ChildPath $_.Name
    # just to see if the input from the csv will give you the desired source and destination paths:
    Write-Host "Copying files from '$($_.FullName)' to folder '$dest'"
    Copy-ExcludeFolders -SourceFolder $_.FullName -Destination $dest -Exclude $exclude -Force -Verbose
}

这是复制后的结果:

D:\COPIEDPROFILES
+---H107371a
|   |   test.txt
|   |
|   +---Folder1
|   |       blah.txt
|   |       somepicture.jpg
|   |
|   \---Folder2
|           myvideo.mp4
|           whatever.txt
|
+---m763671
|   |   test.txt
|   |
|   +---FolderA
|   |       blah1.txt
|   |       somepicture1.jpg
|   |
|   \---FolderB
|           myvideo1.mp4
|           whatever1.txt
|
+---W575288
|   |   test.txt
|   |
|   +---FolderX
|   |       blah2.txt
|   |       somepicture2.jpg
|   |
|   \---FolderY
|           myvideo2.mp4
|           whatever2.txt
|
\---W575288a
    |   test.txt
    |
    +---Another-Folder
    |       myvideo3.mp4
    |       whatever3.txt
    |
    \---Some-Folder
            blah3.txt
            somepicture3.jpg

如果您有不同的结果,请更正您的输入 csv,以便文件在列中具有正确的 SourceFolderFullName和正确的目标子文件夹名称,以在参数中创建目标文件夹Destination


推荐阅读